简单工厂----》工厂模式-----》抽象工厂。 桃扇骨 2021-12-01 12:20 365阅读 0赞 # 工厂模式 # > 考虑使用静态工厂方法代替构造器 -----《Effective Java》 > > 静态工厂通常更加合适。因此切忌第一反应就是提供公有地构造器,而不先考虑静态工厂。 问题: 我们遇到需要对象地地方就使用new 关键字。当然 new 本身没有任何错,但是在修改了一些业务逻辑后,往往我们需要改变很多new 出来地对象地相关代码。业务代码地修改部分竟如此疯狂. 如果我们能将new出来不同地类地代码提取到一个专用的类中,在修改时将会有很大好处。 ## 工厂方法模式的优点 ## > 低耦合、高内聚,开放封闭原则(在很多工厂方法中不符合这一点) ## 工厂模式的三种工厂 ## ### 1. 简单工厂 ### 描述: 通过传入参数,返回不同的对象。重点在于:将通过参数获得不同的对象的代码,从逻辑代码中提取出来,成为一个单独的类. 代码举例: // 原来的代码 void buyCar() { // 得到用户输入的车名 // 通过if语句new出相应的对象 Car car = null; String name = scanner.nextLine(); if(name.equals("BW")) { car = new BWCar(); } else if (name.equals("ABC")) { car = new ABCCar(); } else { }// 等等 // 走购买流程 } // 注意:此时逻辑与新建对象混杂在一起. // 当需要改变这段代码时,需要大费周章的找到所有类似逻辑 /** * 提取对象. */ void buyCar() { // 得到用户输入的车名 // 通过if语句new出相应的对象 // 可能会改变地逻辑被提取。 String name = scanner.nextLine(); Car car = CarFactory.newCarInstance(name); // 走购买流程 } // 将其提取到一个专用的类中:面向对象。 public class CarFactory { static Car newCarInstance(String carName) { // 通过if语句new出相应的对象 if(name.equals("BW")) { car = new BWCar(); } else if (name.equals("ABC")) { car = new ABCCar(); } else { // 等等 } } } // Oh,别了吧,不就是换了个地方吗? // 事实上,就是将代码从逻辑中提取到一个单独的类中。 // 但是当ABC车厂倒闭时,你只需要修改CarFactor即可,不再需要去逐个修改业务代码. // 能有效地将与业务代码无关的部分分离出来,当需要修改车地类型(有的车厂倒闭了,新建了车厂) // 此时不再修改任务业务类,只需要在CarFactory中进行简单修改,就可以保证代码地正确性. PS : 我们在这里使用的是静态工厂,static关键字修饰了newInstance()方法。当然坏处就是无法通过继承的方式来改变这个方法。 总结:简单工厂并不算是一种模式,更像是一种编程习惯,但总的来说是一个很棒的编程习惯。 ### 工厂方法模式 ### 简单工厂中,我们通过参数控制返回的对象。但是这可不是一个好事情,通过参数控制很像面向过程的思维,我们应该使用对象,让对象去控制这个流程。 场景:在上面的代码中我们所有工厂都是通过简单的new新建一个车,但是事实上我们都知道一个牌子的车也是有三六九等的。 ![1563588620590][] CarFactory改成一个抽象类,newCarInstance()改成抽象方法,由各个子类自己去实现,每个子类依然是一个简单工厂,这样每个工厂想生产什么就自己控制自己的代码。 PS : 这一下就从计划经济便成为宏观市场(通过类自己选择)微观计划(在类中依然是计划). 比如我现在想买一个BW出的至尊车。 void buyCar() { // 通过多态,控制对应的工厂类. Carfactory carFactory = new BWFactory(); String name = "至尊"; // 使用简单工厂. carFactory.newInstance(name); } 实际上,我们可以看到就是使用了面向对象的多态性,让对象帮我们做选择。 缺点:随着代码的发展,各种各样的产品的出现,其对应的工厂会越来越多,大众创业的情况下,将会出现非常多的牌子,造成类爆炸。 总结:可以理解工厂方法就是通过面向接口/多态性,来使子类做出自己独一无二的抉择.工厂方法对产品的扩展支持的很好,但工厂的扩展可能会造成工厂数量爆炸,难以管理。 ### 抽象工厂 ### 工厂方法作为简单工厂的延申,成功解决了简单工厂的, 我们通过依赖倒置,让所有的工厂依赖CarFactory,让CarFactory生产汽车和公交车。 ![1563602445382][] 现在买车的逻辑有些变化: > 我要买那个牌子的汽车? =====>CarFactory factory = new BWCarFactory(); > > 我想买一辆便宜车. =====> CheapCar cheapCar = new CheapCar(factory); > > 我想买那个牌子的公交车=====>CarFactory factory = new ChinaBusFactory(); > > 电动的就可以 ======>ElectricBus bus = new ElectricBus(factory); 在建造便宜车时,所有的零件都将来自BW工厂,最后生成一个价格低廉,性能较差的车辆,并且含有BW的商标。 好处很明显,对于各种各样的CarFactory,无论新增还是删除或者修改,业务代码都可以不用修改,也可以轻松的扩展出卡车工厂,三轮车工厂。 坏处就在于:产品的改变,如果现在需要生产一个"活动车",那么对于CarFactory接口,就需要做出改变,从而影响所有的CarFactory,比如我现在增加一个三轮车工厂,那么车工厂就需要增加生产三轮车的功能,那么之前所有CarFactory都必须增加一个生产三轮车的方法,那么他们仅仅只在方法中说:”抱歉,这个牌子不生产三轮车”。 很明显可以看出:抽象工厂是管理工厂时的工厂,但是其对产品的支持度较差。与工厂方法相反。 ## 总结 ## 当你需要创建产品 家族和想让制造的相关产品集合起来时,你可以使用抽象工厂。 当你需要把业务代码中的“实例化的具体类”中解耦出来,或者你目前还不知道将来需要实例化那些具体类时,可以用工厂方法。只需要继承工厂成为一个子类,并实现对应的工厂就可以了。 当你单纯的只是想要把业务代码中的“实例化的具体类”中解耦出来,你可以使用简单工厂,当然简单工厂并不是一种模式,它更像一种编程习惯。 [1563588620590]: /images/20211201/5936d22509d34a7e88ba8925eba65efe.png [1563602445382]: /images/20211201/dad4c41ca4634e55a9d70965de2db317.png
还没有评论,来说两句吧...