Python设计模式系列之四: 创建型Abstract Factory模式

 

2003 年 7 月 03 日

软件设计大师总是要比初学者更加清楚该如何设计软件,因为他们手中掌握着设计模式这一法宝。作为一种高级的软件复用形式,设计模式是众多优秀软件设计师集体智慧的结晶,能够很好地指导软件设计过程。本系列文章讲述如何在用Python开发软件时应用各种设计模式,此次介绍的是创建型工厂方法(Factory Method)模式。

一、简介

抽象工厂(Abstract Factory)模式又称为Kit模式,属于对象创建型模式,它拥有比简单工厂模式和工厂方法模式更高的抽象性,是所有工厂模式中最为抽象和最具一般性的形态。抽象工厂模式是一种重要的架构型组件(Architectural Component),它负责提供统一的接口,用来生成一簇"相互关联"或者"相互依赖"的多态对象(Polymorphic Object)。

考虑一个具有多种风格(Theme)的GUI工具包,它能够同时支持KDE和GNOME等类型的桌面环境,不同的桌面风格负责为诸如按钮、文本框和滚动条这样的窗口控件(Widget)定义不同的外观和行为。很显然,应用程序不应该针对某种特定的桌面风格硬编码它的窗口控件,否则之后如果需要使用另外一种桌面风格就必须对源代码进行修改,或者换句话说,在应用程序中实例化特定桌面风格的窗口控件将使得今后很难再对应用程序的桌面风格进行更改。解决的办法是首先定义一个抽象的WidgetFactory类,它负责声明用于创建每一类窗口控件的公共接口,然后再为每一类窗口控件定义一个共同的抽象父类,并且使用与之对应的具体子类来实现特定风格的窗口控件。对于每一个抽象的窗口控件类,WidgetFactory都提供一个返回相应对象的方法,这样应用程序就可以通过调用这些方法来获得窗口控件的实例,而不用关心当前正在使用的是哪些具体类,从而也就可以不再依赖于某种具体的桌面风格了,整个GUI工具包的系统结构如图1所示。

图1

每一种桌面风格都对应于WidgetFactory的一个具体子类,它们负责实现在WidgetFactory中定义的用来创建相应窗口控件的方法。例如,调用KDEWidgetFactory中的createButton()方法可以创建一个KDE桌面环境下的按钮,而调用GNOMEWidgetFactory中的createButton()方法则可以创建一个GNOME桌面环境下的按钮。此处的WidgetFactory就是一个抽象工厂,它使得应用程序只需通过在WidgetFactory中定义的接口就可以得到相应的窗口控件,而不用关心整个GUI软件包中究竟是哪些类实现了特定风格的窗口控件。运用抽象工厂模式的好处是客户端可以完全独立于产品的创建过程,只要与抽象工厂类中定义的公共接口进行交互就可以了,而无需对具体的产品类进行实例化操作。

抽象工厂模式与工厂方法模式最大的区别在于:工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则针对的是多个产品等级结构。正因如此,在抽象工厂模式中经常会用到产品族(Product Family)这一概念,它指的是位于不同的产品等级结构中,并且功能相互关联的产品系列。图2中箭头所指的就是三个功能相互关联的产品,它们位于三个不同的产品等级结构中的相同位置上,共同组成了一个产品族。

图2

不难看出,如果使用抽象工厂模式,那么仅需要一个工厂等级结构就可以创建出分属于不同产品等级结构的产品族中的所有对象,因此抽象工厂模式同工厂方法模式相比效率更高。抽象工厂这一模式适合在如下场合中运用:

  • 当软件系统要求独立于产品的创建、组合和表示的时候,其实这对任何形态的工厂模式来讲这都是很重要的。
  • 当软件系统要由多个产品族中的一个来进行配置的时候,此时系统中会存在多于一个的产品族,但同一时刻只会消费其中某一族的产品,这是抽象工厂模式的原始用意。
  • 当一簇相关产品被设计成应该被组合使用的时候,即同属于某个产品族的多个产品是需要在一起配套使用的,这一约束必须在系统设计时体现出来。
  • 当需要提供一个产品库,并且只想暴露接口而不是实现的时候,这样所有的产品都能够以同样的接口出现,从而使得客户端可以不依赖于具体的实现。





回页首

二、模式引入

抽象工厂模式的一个主要功能是它能够隔离要生成的具体产品类,由于这些类的实际类名都被隐藏在工厂里面,因此客户端根本不需要关心如何对它们进行实例化的细节。每一种设计模式都是针对特定问题的解决方案,而抽象工厂模式面临的问题则是当涉及到有多个产品等级结构时,如何更好地进行软件体系结构的设计。下面从一个具体的问题出发,将抽象工厂模式引入到软件系统的设计中来。

假设我们打算开发一个类似于Doom或者Quake那样的格斗类游戏,为了适应不同等级玩家的需要,游戏特地安排了两个难度级别:初等级别和高难级别。在初等级别中,敌方士兵反映迟钝,怪兽步履缓慢,即便是初学者也能够很轻松地取胜;但在高难级别中,敌方士兵反映敏捷,怪兽狰狞狡诈,就算是高级玩家也难逃被击毙的厄运。

在具体实现时可以先设计两个抽象产品类Soldier和Monster,用来代表士兵和怪兽,然后再分别从它们派生出SillySoldier和SillyMonster两个具体产品类用于初等级别,以及WiseSoldier和WiseMonster两个具体产品类用于高难级别。设计时一个值得注意的问题是,游戏在运行的过程中SillySoldier和WiseMonster是绝对不能同时出现的,因为玩家要么就与SillySoldier和SillyMonster进行实战演练,要么就与WiseSoldier和WiseMonster展开艰苦的战斗。不难看出,游戏在设计时依据难度级别形成了两个产品族,玩家在游戏期间肯定会使用这两个产品族中的某一族对象,但绝对不会同时使用它们。

为了保证这种一致性,程序员在编码时必须非常小心,否则稍有疏忽,那些正在痛击SillySoldier的游戏菜鸟们一转身撞上一个WiseMonster,肯定会败得一塌糊涂。抽象工厂模式可以很好地解决这一问题,在具体实现时可以先将游戏中所有Soldier和Monster对象的生成函数集中到一个抽象工厂AbstractEnemyFactory中,然后再根据不同的难度级别依次构造SillyEnemyFactory和WiseEnemyFactory两个具体工厂,并由它们负责按照当前游戏策略的要求去生成具体的士兵和怪兽。这样一来,整个游戏的体系结构就将如图3所示。

图3

AbstractEnemyFactory 是一个抽象工厂,它负责声明被所有具体工厂所共有的构造性方法,其完整的代码如清单1所示。在AbstractEnemyFactory中定义的createSoldier()和createMonster()是两个抽象方法,它们必须在所有的具体工厂中给出相应的实现,这样客户端才有可能通过调用具体工厂中的这两个方法,来获得所需要的某种Soldier或者Monster对象。


        代码清单1:abstractenemyfactory.py
class AbstractEnemyFactory:
  """ 负责创建Soldier和Monster的抽象工厂 """
  
  # 创建Soldier的抽象方法
  def createSoldier(self):
    pass
  
  # 创建Monster的抽象方法
  def createMonster(self):
    pass
      

SillyEnemyFactory AbstractEnemyFactory 的一个具体实现,它负责实例化 SillySoldier SillyMonster 对象,其完整的代码如清单2所示。


        代码清单2:sillyenemyfactory.py
from sillysoldier import *
from sillymonster import *
from abstractenemyfactory import *
class SillyEnemyFactory(AbstractEnemyFactory):
  """ 负责创建SillySoldier和SillyMonster的具体工厂 """
  
  # 创建SillySoldier的具体方法
  def createSoldier(self):
    soldier = SillySoldier()
    return soldier
  
  # 创建SillyMonster的具体方法
  def createMonster(self):
    monster = SillyMonster()
    return monster
      

WiseEnemyFactory AbstractEnemyFactory 的另一个具体实现,它负责实例化 WiseSoldier WiseMonster 对象,其完整的代码如清单3所示。


        代码清单3:wiseenemyfactory.py
from wisesoldier import *
from wisemonster import *
from abstractenemyfactory import *
class WiseEnemyFactory(AbstractEnemyFactory):
  """ 负责创建WiseSoldier和WiseMonster的具体工厂 """
  
  # 创建WiseSoldier的具体方法
  def createSoldier(self):
    soldier = WiseSoldier()
    return soldier
  
  # 创建WiseMonster的具体方法
  def createMonster(self):
    monster = WiseMonster()
    return monster
      

AbstractEnemyFactory SillyEnemyFactory WiseEnemyFactory 共同组成了抽象工厂模式中的工厂等级结构,其作用是为了更好地创建相应的 Soldier Monster 产品对象。 Soldier 是游戏中所有士兵对象的抽象接口,其完整的代码如清单4所示。


        代码清单4:soldier.py
class Soldier:
  """ 所有士兵对象的抽象接口 """
  
  # 获取速度的抽象方法
  def getSpeed(self):
    pass
  
  # 获取武器的抽象方法
  def getWeapon(self):
    pass
      

SillySoldier Soldier 的一个具体实现,它用来代表初等游戏级别中的士兵对象,其完整的代码如清5所示。


        代码清单5:sillysoldier.py 
from soldier import *
class SillySoldier(Soldier):
  """ 初等级别中士兵对象的具体实现 """
  
  # 构造函数
  def __init__(self):
    print "A SillySoldier is created."
    self.speed = 10
    self.weapon = "saber"
    
  # 获取速度的具体实现
  def getSpeed(self):
    return self.speed
  
  # 获取武器的具体实现
  def getWeapon(self):
    return self.weapon
      

WiseSoldier 则是 Soldier 的另一个具体实现,它用来代表高难游戏级别中的士兵对象,其完整的代码如清单6所示。


        代码清单6:wisesoldier.py
from soldier import *
class WiseSoldier(Soldier):
  """ 高难级别中士兵对象的具体实现 """
  
  # 构造函数
  def __init__(self):
    print "A WiseSoldier is created."
    self.speed = 100
    self.weapon = "gun"    
    
  # 获取速度的具体实现
  def getSpeed(self):
    return self.speed
  
  # 获取武器的具体实现
  def getWeapon(self):
    return self.weapon
      

除了士兵之外,玩家在游戏中可能会遇到的另一类对手就是怪兽,Monster是游戏中所有怪兽对象的抽象接口,其完整的代码如清单7所示。


        代码清单7:monster.py
class Monster:
  """ 所有怪兽对象的抽象接口 """
    
  #  获取体能的抽象方法
  def getVitality(self):
    pass
  
  # 获取智力的抽象方法
  def getIntelligence(self):
    pass
      

SillyMonster是Monster的一个具体实现,它用来代表初等游戏级别中的怪兽对象,其完整的代码如清8所示。


        代码清单8:sillymonster.py
from monster import *
class SillyMonster(Monster):
  """ 初等级别中怪兽对象的具体实现 """
  
  # 构造函数
  def __init__(self):
    print "A SillyMonster is created."
    self.vitality = 20
    self.intelligence = 30
    
  # 获取体能的具体实现
  def getVitality(self):
    return self.vitality
  
  # 获取智力的具体实现
  def getIntelligence(self):
    return self.intelligence
      

WiseMonster则是Monster的另一个具体实现,它用来代表高难游戏级别中的怪兽对象,其完整的代码如清单9所示。


        代码清单9:wisemonster.py
from monster import *
class WiseMonster(Monster):
  """ 高难级别中怪兽对象的具体实现 """
  
  # 构造函数
  def __init__(self):
    print "A WiseMonster is created."
    self.vitality = 90
    self.intelligence = 80
    
  # 获取体能的具体实现
  def getVitality(self):
    return self.vitality
  
  # 获取智力的具体实现
  def getIntelligence(self):
    return self.intelligence
      

从整个游戏的体系结构中不难看出, Soldier SillySoldier WiseSoldier 三者共同构成了一个产品等级结构,而Monster、SillyMonster和WiseMonster则构成了另外一个产品等级结构。这样一来,整个游戏中就出现了三个等级结构:一个工厂等级结构和两个产品等级结构,并且工厂等级结构与产品等级结构完全平行,这是应用抽象工厂模式时最典型的环境。

通过运用抽象工厂模式,客户端在使用时只要创建具体工厂的实例,然后调用工厂对象中的工厂方法,就可以得到所需的产品对象,从而避免了对具体产品对象的实例化操作,其示例性代码如清单10所示。


        代码清单10:game.py
import sys
from sillyenemyfactory import *
from wiseenemyfactory import *
# 主函数
if (__name__ == "__main__"):
  args = sys.argv
  
  # 根据游戏等级生成具体工厂
  if ("silly" in args):
    factory = SillyEnemyFactory()
  elif ("wise" in args):
    factory = WiseEnemyFactory()
  else:
    print "Usage: python game.py silly|wise"
    exit
  # 通过具体工厂创建士兵和怪兽
  soldier = factory.createSoldier()
  monster = factory.createMonster()
    
  # 获得士兵和怪兽的当前状态
  print "Soldier speed is %d" %(soldier.getSpeed())
  print "Soldier weapon is %s" % (soldier.getWeapon())
  print "Monster vitality is %d" % (monster.getVitality())
  print "Monster intelligence is %d" % (monster.getIntelligence())
      





回页首

三、一般结构

抽象工厂模式是工厂方法模式的进一步抽象和推广,当一个软件系统需要产生一些产品对象,并且这些产品分属于多个产品等级结构时,为了将消费这些产品对象的职责和创建这些产品对象的职责分割开来,可以借助于抽象工厂模式。通过运用抽象工厂模式,消费产品的客户端无需直接参与产品的创建工作,而只用向一个公共的工厂接口请求所需的产品就可以了。抽象工厂模式的一般性结构如图4所示,图中为了简化只给出了具有两个层次的产品族(抽象层次和具体层次),但实际系统往往都会具有更加复杂的等级结构。

图4

抽象工厂模式面对的是具有相同或者相似等级结构的多个产品族,它可以很好地解决在多个产品族中创建多个产品对象时的一致性问题。从上图中可以看出,抽象工厂模式涉及到抽象工厂角色、具体工厂角色、抽象产品角色和具体产品角色四个参与者。

  • 抽象工厂(Abstract Factory)角色  是抽象工厂模式的核心,它负责定义创建抽象产品对象的接口。抽象工厂不能被外界直接调用,但任何在模式中用于创建具体产品对象的工厂类都必须从抽象工厂派生,并且实现由它定义的所有工厂方法。
  • 具体工厂(Concrete Factory)角色  是抽象工厂模式的对外接口,它负责实现创建具体产品对象的内部逻辑。具体工厂与应用密切相关,可以被外界直接调用,创建所需要的产品。
  • 抽象产品(Abstract Product)角色  是抽象工厂模式所创建的某一类产品对象的抽象父类,它负责描述某些具体产品所共有的公共接口。
  • 具体产品(Concrete Product)角色  是抽象工厂模式的创建目标,所有创建的对象都是充当这一角色的某个具体产品类的实例。

抽象工厂角色负责声明用来"生产"抽象产品的工厂方法,在抽象工厂角色中定义的工厂方法通常来讲会有多个,分别用于创建不同产品等级结构中的产品对象。以下是抽象工厂类AbstractFactory的示例性Python代码。


        代码清单11:abstractfactory.py
class AbstractFactory:
  """ 抽象工厂角色 """
  
  # 用于创建产品等级结构A中抽象对象的工厂方法
  def createProductA(self):
    pass
  
  # 用于创建产品等级结构B中抽象对象的工厂方法
  def createProductB(self):
    pass
      

具体工厂角色则负责创建产品等级结构中某类具体产品的实例,并将其返回给调用者。具体工厂是与具体产品族相关的,实现时常用的做法是为每个产品族定义一个具体工厂。以下是具体工厂类ConcreteFactory1的示例性Python代码:


        代码清单12:concretefactory1.py
class ConcreteFactory1(AbstractFactory):
  """ 具体工厂角色1 """
  
  # 用于创建产品等级结构A中具体对象的工厂方法
  def createProductA(self):
    product = ConcreteProductA1()
    return product
  
  # 用于创建产品等级结构B中具体对象的工厂方法
  def createProductB(self):
    product = ConcreteProductB1()
    return product
      

一般而言,有多少个产品等级结构,就会在抽象工厂角色中发现多少个工厂方法。在每一个产品等级结构中有多少个具体产品,就会有多少个产品族,同时也就会在工厂等级结构中发现多少个具体工厂。以下是具体工厂类ConcreteFactory2的示例性Python代码:


        代码清单13:concretefactory2.py
class ConcreteFactory2(AbstractFactory):
  """  具体工厂角色2 """
  
  # 用于创建产品等级结构A中具体对象的工厂方法
  def createProductA(self):
    product = ConcreteProductA2()
    return product
  
  # 用于创建产品等级结构B中具体对象的工厂方法
  def createProductB(self):
    product = ConcreteProductB2()
    return product
      

抽象产品角色的主要目的是为某一类具体产品提供一个共同的接口,通常只需提供相应的声明就可以了,而不用给出具体的实现。以下是产品等级结构A中抽象产品类AbstractProductA的示例性Python代码:


        代码清单14:abstractproducta.py
class AbstractProductA:
  """ 产品等级结构A中的抽象产品角色  """
  
  # 产品等级结构A中所有产品类的公共接口
  def interface(self):
    pass
      

具体产品角色充当最终的创建目标,一般来讲它是抽象产品类的子类,实现了抽象产品类中定义的所有工厂方法,实际应用时通常会具有比较复杂的业务逻辑。以下是产品等级结构A中具体产品类ConcreateProductA1的示例性Python代码:


        代码清单15:concreteproducta1.py
class ConcreateProductA1(AbstractProductA):
  """ 产品等级结构A中的具体产品角色1 """
  
  # 产品等级结构A中公共接口的实现
  def interface(self):
    print "ConcreateProductA1 method."
      

通常来说,在同一个产品等级结构中充当具体产品的角色会有多个,以下是产品等级结构A中具体产品类ConcreateProductA2的示例性Python代码:


        代码清单16:concreteproducta2.py
class ConcreateProductA2(AbstractProductA):
  """ 产品等级结构A中的具体产品角色2 """
  
  # 产品等级结构A中公共接口的实现
  def interface(self):
    print "ConcreateProductA2 method."
      

AbstractProductA、ConcreateProductA1和ConcreateProductA2共同构成了产品等级结构A,在前面给出的抽象工厂模式的一般性结构中,还存在另外一个产品等级结构B,以下是产品等级结构B中抽象产品类AbstractProductB的示例性Python代码:


        代码清单17:abstractproductb.py
class AbstractProductB:
  """ 产品等级结构B中的抽象产品角色  """
  
  # 产品等级结构B中所有产品类的公共接口
  def interface(self):
    pass
      

具体产品类ConcreateProductB1位于产品等级结构B中,它实现了产品等级结构B的抽象产品接口,以下是其示例性Python代码:


        代码清单18:concreteproductb1.py

class ConcreateProductB1(AbstractProductB):
  """ 产品等级结构B中的具体产品角色1 """
  
  # 产品等级结构B中公共接口的实现
  def interface(self):
    print "ConcreateProductB1 method."
      

具体产品类ConcreateProductB2同样位于产品等级结构B中,它实现了产品等级结构B的抽象产品接口,以下是其示例性Python代码:


        代码清单19:concreteproductb2.py
class ConcreateProductB2(AbstractProductB):
  """ 产品等级结构B中的具体产品角色2 """
  
  # 产品等级结构B中公共接口的实现
  def interface(self):
    print "ConcreateProductB2 method."
      

在应用抽象工厂模式时,通常还需要再引入一个客户端角色,由它负责创建具体的工厂对象,然后再调用工厂对象中的工厂方法来创建相应的产品对象。以下是客户端的示例性Python代码:


        代码清单13:client.py
class Client:
  """ 客户端角色 """
  
  def run(self):
    factory = ConcreteFactory1()
    product = factory.createProductA()
    product.interface()
# 主函数
if (__name__ == "__main__"):
  client = Client()
  client.run()
      

在这个简单的抽象工厂模式的示意性实现里,只给出了两个产品等级结构,而每个产品等级结构中又恰好只有两个具体产品,因而将形成两个产品族。与之对应的是,在工厂等级结构中会出现两个具体工厂(对应于两个产品族),而每个工厂类中又会有两个工厂方法(对应于两个产品等级结构)。但在真正的实际应用中,产品等级结构的数目与每个产品等级结构中具体产品的数目(即产品族的数目)一般来讲是不会相等的。

抽象工厂模式的活动序列如图5所示,客户端Client首先创建ConcreteFactory对象,然后调用ConcreteFactory对象的工厂方法createProduct(),由它负责"生产"出所需要的ConcreteProduct对象,而AbstractFactory的作用只是将产品对象的创建延迟到它的子类ConcreteFactory中实现。在抽象工厂模式中,每一个具体工厂都只负责创建某一类特定的产品对象,如果要想创建不同种类的产品对象,客户端必须使用不同的具体工厂。

图5





回页首

四、实际运用

在抽象工厂模式中,AbstractFactory仅负责声明一系列用于创建产品对象的公共接口,真正实例化产品的工作是由ConcreteFactory子类来完成的。在实际中运用抽象工厂模式时,通常需要和工厂方法模式结合起来一同使用,即为每一个产品定义一个工厂方法,由它来负责调用产品的构造函数,对产品角色进行实例化操作。这种方法虽然实现起来比较容易,但却要求为系统中的每个产品族都定义一个具体工厂类,即便这些产品族之间的差异非常小也是如此。

AbstractFactory是整个抽象工厂模式的核心,它为所有可能生产出的产品都定义了相应的操作,也就是说产品的种类实际上是硬编码在代码中的,因此增加一种新的产品同时也就意味着要改变AbstractFactory接口以及所有与它相关的类。实际运用时可以采用一个更为灵活的方法,即在抽象工厂角色中添加一个静态的类方法,该方法接受一个参数,并可以根据参数值返回所需具体工厂的实例。

在实际的软件系统中应用抽象工厂模式时,另外需要考虑的一个重要因素就是"开-闭"原则(Open-Close Principle,OCP),简单说来就是软件系统应当对扩展开放,同时对修改封闭。几乎所有的软件系统都不可避免地面临着一个共同的难题,那就是对它们的需求总是在随着时间的推移而发生某种程度的变化,而解决这一问题的关键就在于抽象。满足"开-闭"原则的软件系统在面临新的需求时,可以通过扩展现有的系统来提供新的行为,从而使得变化中的软件系统有一定的适应性和灵活性;此外,满足"开-闭"原则的软件系统中的已有模块,特别是那些重要的抽象层模块不能够再被修改,这就使得变化中的软件系统又有着一定的稳定性和延续性。

"开-闭"原则要求软件系统能够在不修改原有代码的基础上,通过扩展达到增强其功能的目的,对于应用了抽象工厂模式的软件系统来讲,其功能的扩充无外乎增加新的产品族和增加新的产品等级结构两种情况。在产品等级结构数目不变的情况下添加新的产品族,也就意味着在每一个产品等级结构中都要增加一个或多个具体产品角色。由于抽象工厂模式中的工厂等级结构是和产品等级结构完全平行的,因此当产品等级结构有所调整时,只需再对工厂等级结构做相应的调整就可以了,此时抽象工厂模式是支持"开-闭"原则的。但如果是在产品族数目不变的情况下添加新的产品等级结构,那就需要对所有的工厂角色进行修改,为每一个工厂类都添加一个新的工厂方法,很显然抽象工厂模式此时是不支持"开-闭"原则的。

总而言之,抽象工厂模式只能以一种非均衡的方式来支持软件系统在功能上的扩展,它可以为新产品族的增加提供很好的支持,但却不能为新的产品等级结构的增加提供同样的便利,实际运用时这一点必须仔细加以考虑。





回页首

五、优势和不足

在抽象工厂模式中,各种具体工厂类被用来创建客户所需要的产品,并负责向客户隐藏哪些具体产品类将被实例化这一细节。运用抽象工厂模式可以有效地控制产品的创建过程,它通过工厂来封装具体产品的实例化过程,从而实现了客户端逻辑与产品创建逻辑的有效分离。客户端只需要通过抽象工厂提供的统一接口,就可以获得所需的产品实例,甚至连具体产品的类名也在具体工厂的实现中被分离出来了,而不会出现在客户端代码中。

通常来说,一个具体工厂类在抽象工厂模式中只会出现一次(即在初始化的时候),这就使得更换一个具体工厂变得相对容易起来。由于所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。例如,在前面介绍的GUI工具包例子中,只需将KDEWidgetFactory工厂对象替换成GNOMEWidgetFactory工厂对象,就可以很轻松地改变整个软件的界面效果。

使用抽象工厂模式的突出优点是当一个产品族中的多个对象被设计成一起工作时,能够保证客户端始终只使用同一个产品族中的对象,这对一些需要根据当前环境来决定其行为的软件系统来说,是非常实用的一种设计模式。

使用抽象工厂模式的缺点是在添加新的产品对象时,难以扩展抽象工厂以便生产新种类的产品,这是因为AbstractFactory接口规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对AbstractFactory及其所有子类的修改,显然不是一个优雅的做法。





回页首

六、小结

抽象工厂模式的核心思想是提供创建一系列相互关联或者相互依赖对象的接口,它由工厂而不是客户来决定需要被实例化的类,通常在构造软件系统的整体框架时被用到。使用抽象工厂模式的一个主要原因是由于它能够将产品类和它们的实例化过程完全分离开来,开发人员很容易对一组具体产品类进行替换。本文代码可供 下载。


参考资料

  • 《面向模式的软件体系结构 卷1:模式系统》,Frank Buschmann等著,贲可荣等译,北京:机械工业出版,2003。


  • 《设计模式 可复用面向对象软件的基础》,Erich Gamma等著,李英军等译,北京:机械工业出版,2000。


  • 《设计模式解析》,Alan Shalloway等著,北京:中国电力出版社,2003。


  • 《C++设计新思维 泛型编程与设计模式之应用》,Andrei Alexandrescu著,侯捷等译,武汉:华中科技大学出版社,2003。


  • 《深入学习:Python程序开发》,Andre Lessa著,张晓晖等译,北京:电子工业出版社,2001。


  • 《Python语言入门》,Mark Lutz等著,陈革等译,2001。


  • 《Python编程金典》,H.M.Deitel等著,周靖译,2003。


  • 从Python官方网站(http://www.python.org)上可以了解到所有关于Python的知识。


  • 在网站http://hillside.net/patterns/上可以了解到许多与模式相关的信息。


关于作者

 

本文作者 肖文鹏是北京理工大学计算机系的一名硕士研究生,主要从事操作系统和分布式计算环境的研究,喜爱Linux和Python。你可以通过 [email protected]与他取得联系。

你可能感兴趣的:(Python设计模式系列之四: 创建型Abstract Factory模式)