从“把大象装进冰箱”来谈谈面向对象程序设计
引子
把大象装进冰箱需要3步:打开冰箱门,把大象装入冰箱,关闭冰箱门。
扩展一下,我们考虑把动物装进冰箱的场景。比如,把猪🐷装进冰箱,把狗🐶装进冰箱,等等。
怎么利用面向对象的思想来进行程序设计呢?
talk is cheap, show me the code.
把大象装进冰箱的程序设计及实现
把大象装进冰箱,这个比较简单,简单到只有某些初级程序员写不出来。
如下,估计都是这个玩法。
代码就不贴了。
把动物装进冰箱的程序设计及实现
推而广之,要把不同的动物装进冰箱,并且假定每种动物装进冰箱的方式不同。那么,该怎么进行程序设计来实现这个需求呢?
程序结构图
类结构图
model-模型类
Animal是抽象类(你可以new一头大象,一条狗,但你总不能new一个动物吧):
package com.animal2icebox.model; import lombok.Data; @Data public abstract class Animal { String name; }
大象模型类-Elephant:
package com.animal2icebox.model; import lombok.Data; @Data public class Elephant extends Animal { int weight; }
狗狗模型类-Dog:
package com.animal2icebox.model; import lombok.Data; @Data public class Dog extends Animal { /** * 狗狗品种 */ String breed; }
重点是把动物装进冰箱的服务类
AnimalIntoIceboxService是抽象基类,提供了把动物装进冰箱的门面方法。但是由于每一种动物装入冰箱的方式各不相同,所以,要暴露接口(抽象方法)给派生类来实现。
package com.animal2icebox.service; import com.animal2icebox.model.Animal; public abstract class AnimalIntoIceboxService { IceboxService iceboxService=new IceboxService(); public void putIntoIcebox(Animal animal) { System.out.println("============================="); iceboxService.openTheDoor(); input(animal); iceboxService.closeTheDoor(); } protected abstract void input(Animal animal); }
把大象装进冰箱-ElephantIntoIceboxService:
package com.animal2icebox.service; import com.animal2icebox.model.Animal; import com.animal2icebox.model.Elephant; public class ElephantIntoIceboxService extends AnimalIntoIceboxService { @Override protected void input(Animal animal) { Elephant elephant = (Elephant) animal; System.out.println(String.format("大象信息:name=%s,重量=%s吨", elephant.getName(), elephant.getWeight())); int threshold = 5; int i = 0; for (i = threshold; i <= elephant.getWeight(); i += threshold) { System.out.println(String.format("这头大象重%s吨,已放入%s吨", elephant.getWeight(), threshold)); } i -= threshold; if (elephant.getWeight() > i) { System.out.println(String.format("这头大象重%s吨,已放入%s吨", elephant.getWeight(), elephant.getWeight() - i)); } System.out.println("已成功把大象装进冰箱!"); } }
把狗狗装进冰箱-DogIntoIceboxService:
package com.animal2icebox.service; import com.animal2icebox.model.Animal; import com.animal2icebox.model.Dog; public class DogIntoIceboxService extends AnimalIntoIceboxService { @Override protected void input(Animal animal) { System.out.println("撒狗粮 here"); Dog dog=(Dog)animal; String words = String.format("%s(品种=%s)", dog.getName(), dog.getBreed()); System.out.println("Hi " + words + ", welcome into the icebox..."); } }
AnimalIntoIceboxFactory-工厂-生产的产品是上面的装进冰箱的动物service类对象
package com.animal2icebox.factory; import com.animal2icebox.model.Animal; import com.animal2icebox.model.Dog; import com.animal2icebox.model.Elephant; import com.animal2icebox.service.AnimalIntoIceboxService; import com.animal2icebox.service.DogIntoIceboxService; import com.animal2icebox.service.ElephantIntoIceboxService; import lombok.Getter; public class AnimalIntoIceboxFactory { public static AnimalIntoIceboxService getServiceInstance(Animal animal) { Class<AnimalIntoIceboxService> serviceClass = AnimalIntoBoxEnum.getServiceClass(animal); assert serviceClass != null; try { return serviceClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } return null; } @Getter enum AnimalIntoBoxEnum { Elephants(Elephant.class, ElephantIntoIceboxService.class), Dogs(Dog.class, DogIntoIceboxService.class), ; Class<Animal> animalClass; Class<AnimalIntoIceboxService> serviceClass; <E extends Animal, S extends AnimalIntoIceboxService> AnimalIntoBoxEnum(Class<E> animalClass, Class<S> serviceType) { this.animalClass = (Class<Animal>) animalClass; this.serviceClass = (Class<AnimalIntoIceboxService>) serviceType; } public static Class<AnimalIntoIceboxService> getServiceClass(Animal animal) { AnimalIntoBoxEnum[] values = AnimalIntoBoxEnum.values(); for (AnimalIntoBoxEnum anEnum : values) { if (anEnum.animalClass.equals(animal.getClass())) { return anEnum.getServiceClass(); } } return null; } } }
AnimalIntoIceboxContext-上下文容器,供外部调用
package com.animal2icebox.context; import com.animal2icebox.factory.AnimalIntoIceboxFactory; import com.animal2icebox.model.Animal; import com.animal2icebox.model.Dog; import com.animal2icebox.model.Elephant; import com.animal2icebox.service.AnimalIntoIceboxService; import java.util.ArrayList; import java.util.List; public class AnimalIntoIceboxContext { public void putAnimalIntoIcebox(List<Animal> animals) { for (Animal animal : animals) { AnimalIntoIceboxService elephantIntoIceboxService = AnimalIntoIceboxFactory.getServiceInstance(animal); assert elephantIntoIceboxService != null; elephantIntoIceboxService.putIntoIcebox(animal); } } }
来吧,开启调用之旅
package com.animal2icebox; import com.animal2icebox.context.AnimalIntoIceboxContext; import com.animal2icebox.model.Animal; import com.animal2icebox.model.Dog; import com.animal2icebox.model.Elephant; import java.util.ArrayList; import java.util.List; public class AnimalIntoIceboxTest { public static void main(String[] args) { List<Animal> animals = new ArrayList<>(); Elephant elephant1 = new Elephant(); elephant1.setName("Emily"); elephant1.setWeight(13); animals.add(elephant1); Dog dog = new Dog(); dog.setName("Lucky"); dog.setBreed("dhole"); animals.add(dog); Elephant elephant2 = new Elephant(); elephant2.setName("包包大人"); elephant2.setWeight(2); animals.add(elephant2); AnimalIntoIceboxContext context=new AnimalIntoIceboxContext(); context.putAnimalIntoIcebox(animals); } }
程序运行结果:
============================= the door is open. 大象信息:name=Emily,重量=13吨 这头大象重13吨,已放入5吨 这头大象重13吨,已放入5吨 这头大象重13吨,已放入3吨 已成功把大象装进冰箱! the door is closed. ============================= the door is open. 撒狗粮 here Hi Lucky(品种=dhole), welcome into the icebox... the door is closed. ============================= the door is open. 大象信息:name=包包大人,重量=2吨 这头大象重2吨,已放入2吨 已成功把大象装进冰箱! the door is closed.
so,本文在“把动物装进冰箱”这个需求场景里,使用了哪些设计模式或设计思想呢?
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/16366630.html