抽象工厂模式
抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。
在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。
所谓产品族,比如AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。而这两个家族都来自于三个产品等级:主板、芯片组、CPU。一个等级结构是由相同的结构的产品组成
上面所给出的三个不同的等级结构具有平行的结构。因此,如果采用工厂方法模式,就势必要使用三个独立的工厂等级结构来对付这三个产品等级结构。
由于这三个产品等级结构的相似性,会导致三个平行的工厂等级结构。随着产品等级结构的数目的增加,工厂方法模式所给出的工厂等级结构的数目也会随之增加。
那么,是否可以使用同一个工厂等级结构来对付这些相同或者极为相似的产品等级结构呢?当然可以的,而且这就是抽象工厂模式的好处。同一个工厂等级结构负责三个不同产品等级结构中的产品对象的创建。
每一个工厂角色都有两个工厂方法,分别负责创建分属不同产品等级结构的产品对象。
抽象工厂的功能是为一系列相关对象或相互依赖的对象创建一个接口。
由于抽象工厂定义的一系列对象通常是相关或相互依赖的,这些产品对象就构成了一个产品族,也就是抽象工厂定义了一个产品族
这就带来非常大的灵活性,切换产品族的时候,只要提供不同的抽象工厂实现就可以了.
在什么情况下应当使用抽象工厂模式
1.一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2.这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3.同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。(比如:Intel主板必须使用Intel CPU、Intel芯片组)
抽象工厂模式的起源
抽象工厂模式的起源或者最早的应用,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。
在每一个操作系统中,都有一个视窗构建组成的构建家族。在这里就是Button和Text组成的产品族。而每一个视窗构件都构成自己的等级结构,由一个抽象角色给出抽象的功能描述,而由具体子类给出不同操作系统下的具体实现。
抽象工厂模式的优点
分离接口和实现
客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。
使切换产品族变得容易
因为一个具体的工厂实现代表的是一个产品族,比如上面例子的从Intel系列到AMD系列只需要切换一下具体工厂。
抽象工厂模式的缺点
不太容易扩展新的产品
如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。
示例代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- ''' Abstract Factory ''' class AbstractFactory(object): computer_name = '' def createCpu(self): pass def createMainboard(self): pass class IntelFactory(AbstractFactory): computer_name = 'Intel I7-series computer ' def createCpu(self): return IntelCpu('I7-6500') def createMainboard(self): return IntelMainBoard('Intel-6000') class AmdFactory(AbstractFactory): computer_name = 'Amd 4 computer ' def createCpu(self): return AmdCpu('amd444') def createMainboard(self): return AmdMainBoard('AMD-4000') class AbstractCpu(object): series_name = '' instructions = '' arch='' class IntelCpu(AbstractCpu): def __init__(self,series): self.series_name = series class AmdCpu(AbstractCpu): def __init__(self,series): self.series_name = series class AbstractMainboard(object): series_name = '' class IntelMainBoard(AbstractMainboard): def __init__(self,series): self.series_name = series class AmdMainBoard(AbstractMainboard): def __init__(self,series): self.series_name = series class ComputerEngineer(object): def makeComputer(self,factory_obj): self.prepareHardwares(factory_obj) def prepareHardwares(self,factory_obj): self.cpu = factory_obj.createCpu() self.mainboard = factory_obj.createMainboard() info = '''------- computer [%s] info: cpu: %s mainboard: %s -------- End -------- '''% (factory_obj.computer_name,self.cpu.series_name,self.mainboard.series_name) print(info) if __name__ == "__main__": engineer = ComputerEngineer() #装机工程师 intel_factory = IntelFactory() #intel工厂 engineer.makeComputer(intel_factory) amd_factory = AmdFactory() #adm工厂 engineer.makeComputer(amd_factory)
执行结果:
AbstractFactory(父类or基类 )
IntelFactory(AbstractFactory的子类or派生类):作用为进行了创建自定品牌的零件
AmdFactory(AbstractFactory的子类or派生类):作用为进行了创建自定品牌的零件
AbstractCpu(父类or基类 )
IntelCpu(AbstractCpu的子类or派生类):作用为记录cup的型号
AmdCpu(AbstractCpu的子类or派生类):作用为记录cup的型号
AbstractMainboard(父类or基类 )
IntelMainBoard(AbstractMainboard的子类or派生类):作用为记录主板的型号
AmdMainBoard(AbstractMainboard的子类or派生类):作用为记录主板的型号
ComputerEngineer(新式类):作用为根据工厂对象(如IntelFactory())让其组装自身型号的零件
抽象工厂和工厂模式的对比区别:
抽象工厂:规定死了,依赖限制,假上面实验,你用intel的机器只能配置intel的CPU不能配置AMD的CPU(由各自的工厂指定自己的产品生产品牌)
工厂模式:不是固定死的,举例:你可使用intel的机器配置AMD的CPU