抽象工厂模式
概念
工厂
在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。
工厂对象通常包含一个或多个方法,用来创建这个工厂所能创建的各种类型的对象。这些方法可能接收参数,用来指定对象创建的方式,最后返回创建的对象。
有时,特定类型对象的控制过程比简单地创建一个对象更复杂。在这种情况下,工厂对象就派上用场了。工厂对象可能会动态地创建产品对象的类,
或者从对象池中返回一个对象,或者对所创建的对象进行复杂的配置,或者应用其他的操作。
这些类型的对象很有用。几个不同的设计模式都应用了工厂的概念,并可以使用在很多语言中
抽象工厂模式
抽象工厂模式(英语:Abstract factory pattern)是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。
在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内
部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。
举个例子来说,比如一个抽象工厂类叫做DocumentCreator(文档创建器),此类提供创建若干种产品的接口,包括createLetter()(创建信件)和createResume()(创建简历)。
其中,createLetter()返回一个Letter(信件),createResume()返回一个Resume(简历)。系统中还有一些DocumentCreator的具体实现类,包括FancyDocumentCreator和ModernDocumentCreator。
这两个类对DocumentCreator的两个方法分别有不同的实现,用来创建不同的“信件”和“简历”(用FancyDocumentCreator的实例可以创建FancyLetter和FancyResume,用ModernDocumentCreator的实例
可以创建ModernLetter和ModernResume)。这些具体的“信件”和“简历”类均继承自抽象类,即Letter和Resume类。客户端需要创建“信件”或“简历”时,先要得到一个合适的DocumentCreator实例,
然后调用它的方法。一个工厂中创建的每个对象都是同一个主题的(“fancy”或者“modern”)。客户端程序只需要知道得到的对象是“信件”或者“简历”,而不需要知道具体的主题,
因此客户端程序从抽象工厂DocumentCreator中得到了Letter或Resume类的引用,而不是具体类的对象引用。
“工厂”是创建产品(对象)的地方,其目的是将产品的创建与产品的使用分离。抽象工厂模式的目的,是将若干抽象产品的接口与不同主题产品的具体实现分离开。
这样就能在增加新的具体工厂的时候,不用修改引用抽象工厂的客户端代码。
使用抽象工厂模式,能够在具体工厂变化的时候,不用修改使用工厂的客户端代码,甚至是在运行时。然而,使用这种模式或者相似的设计模式,
可能给编写代码带来不必要的复杂性和额外的工作。正确使用设计模式能够抵消这样的“额外工作”。
UML类图

应用场景
当一个对象都有相同的约束时,可以使用抽象工厂模式。
打个比方说,这个工厂的几个产品都需要经过某些共同的步骤和打上相同的商标,这一组产品可以
在一个工厂里面生产,减少很多重复的代码在不同的地方都出现多次。
优缺点
优点
1.针对同一组产品创建新的生产线,只需实现那组产品的抽象工厂接口即可创建新的工厂类。
2.提供一种间接的级别,可以抽象创建相关或依赖的对象的组(family),而不必指定具体的类,
"工厂"对象负责为整个平台系列提供创建服务。客户不直接创建对象,而是通过工厂类来生成这一组对象
3.这种机制使得交换产品系类变得简单,因为工厂类的实例只在程序出现一次初始化,可以通过实
例化不同的具体实例来鼻梁替换整个产品系列
`tips:由于工厂类提供的服务非常普遍,所以通常作为单例实现`
缺点
抽象方法模式的最大缺点就是产品族本身的扩展非常困难。如果在产品族中增加一个新的产品类型,则需要修改多个接口,并影响现已有的工厂类。
与建造者模式(Builder)的对比
Builder着重于逐步构建复杂的对象。抽象工厂强调一系列产品对象(简单或复杂)。
Builder作为最后一步返回产品,但就抽象工厂而言,产品会立即返回。
代码实例
这里设计一个工厂生产奔驰汽车和它对应的导航仪两种产品。
(1) 工厂的抽象接口类
1 | public interface BenzFactory { |
(2) 车辆导航仪的抽象接口类
1 | public interface CarNavigator { |
(3) 车辆的抽象接口类
1 | public interface Benz { |
(4) 生产C180和其导航仪的工厂类
1 | public class C180Factory implements BenzFactory { |
(5) 生产B260和其导航仪的工厂类
1 | public class B260Factory implements BenzFactory { |
(6) 生产C180的类
1 | public class BenzC180 implements Benz { |
(7) 生产B260的类
1 | public class BenzB260 implements Benz { |
(8) 生产C180导航仪的类
1 | public class C180Navigator implements CarNavigator { |
(9) 生产B260导航仪的类
1 | public class B260Navitor implements CarNavigator { |
(10) 测试类
1 | public class TestDemo { |
从以上代码中分析优缺点
优点
生产新的汽车产品和对应的导航仪设备,你只需要创建一个该产品对应的具体工厂和该产品的具体实现类,
变抽象的工厂类和抽象的产品类,具体工厂类和具体产品类需要什么操作已经在抽象接口类定义好了。
缺点
工厂方法的扩展性算是比较好的,而抽象工厂模式的扩展性就没那么好了。
个工厂需要多创建几个产品对象,那么就需要增加抽象工厂的方法,增加抽象接口的方法后,其他实现了抽象工厂接口方法
都需要改变,才能正常编译。
代码示例2
1 | // class CPU |
这段代码更加清晰
实例分析
抽象工厂的目的是提供一个用于创建相关对象族的界面,而不需要指定具体的类。
这种模式可以在日本汽车制造中使用的钣金冲压设备中找到。
冲压设备是一个创建汽车车身零件的抽象工厂。
同样的机器被用来为不同车型的右手门,左手门,右前挡泥板,左前挡泥板,引擎盖等。
通过使用滚轮来更换冲压模具,可以在三分钟内改变机器生产的产品类别。
