创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够使软件模块做到与对象创建和组织的无关性。为了使体系结构更加清晰,一些软件在设计上要求当创建类的具体实例时,能够根据具体的语境来动态地决定怎样创建对象,创建哪些对象,以及怎样组织和表示这些对象,而创建型模式所要描述的就是该如何来解决这些问题。
按照生成目标的不同,创建型模式可以分为类的创建型模式和对象的创建型模式两种:
类的创建型模式
类的创建型模式通过使用继承关系,将类的创建交由具体的子类来完成,这样就向外界隐藏了如何得到具体类的实现细节,以及这些类的实例是如何被创建和组织在一起的。
对象的创建型模式
对象的创建型模式通过把对象的创建委托给另一个对象来完成,可以根据语境动态地决定生成哪些具体类的实例,同时还可以向外界隐藏这些实例是如何被创建以及如何被组织在一起的细节。
所有的创建型模式都有两个永恒的主旋律:第一,它们都将系统使用哪些具体类的信息封装起来;第二,它们隐藏了这些类的实例是如何被创建和组织的。外界对于这些对象只知道它们共同的接口,而不清楚其具体的实现细节。正因如此,创建型模式在创建什么(what),由谁(who)来创建,以及何时(when)创建这些方面,都为软件设计者提供了尽可能大的灵活性。
具体到Python来说,假设有这样一个类:
class Person:
def __init__(self, name):
self.name = name
要创建该类的一个实例,则应该执行下面的语句:
p = Person("Gary")
但如果创建对象时完成的工作非常复杂,需要一段很长的代码,你就不能简单地将其全部写入__init__方法中,因为这会违背面向对象思想的两个基本原则:封装(encapsulation)和委派(delegation)。假如执意要做样做,结果只会使你的代码变成一段行为固定的硬编码(hard coding),而整个软件的结构都极有可能变得非常糟糕,因为其它某个模块也许就正依赖于你所创建的这个实例,这样就在无形之间增加了模块之间的耦合度。
将Python对象的创建过程封装到某个类中来单独完成,可以使你的程序变得更加灵活和通用。实践证明,使用下面的六种创建型模式可以更好地改善对象的创建过程:
Simple Factory模式
专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。
Factory Method模式
将对象的创建交由父类中定义的一个标准方法来完成,而不是其构造函数,究竟应该创建何种对象由具体的子类负责决定。
Abstract Factory模式
提供一个共同的接口来创建相互关联的多个对象。
Singleton模式
保证系统只会产生该类的一个实例,同时还负责向外界提供访问该实例的标准方法。
Builder模式
将复杂对象的创建同它们的具体表现形式(representation)区别开来,这样可以根据需要得到具有不同表现形式的对象。
Prototype模式
利用一个能对自身进行复制的类,使得对象的动态创建变得更加容易。
二、模式引入
简单工厂(Simple Factory)模式又称为静态工厂方法(Static Factory Method)模式,属于类的创建型模式。这种模式根据外界给定的信息,由"工厂"对象"制造"出某些可能"产品"类中的一个实例,工厂对象能够处理的所有类通常都继承于同一个父类,并且对外界提供基本相同的接口,只不过在具体实现时会有所差别罢了。
假设我们要开发一个绘图程序,用来绘制简单的几何图形,这个软件应该能够处理下面的几种几何对象:
圆形(Circle)
矩形(Rectangle)
菱形(Diamond)
除了各自特有的属性和方法之外,所有的几何图形几乎都可以抽象出绘制(draw)和擦除(erase)两个公共方法,因而可以为它们定义一个共同的接口Shape。虽然Python语言本身并不支持接口,但为了更好地阐明设计模式的思想,有时我们还是会借用一下UML中的接口这一概念。这样一来,各个类之间的关系就将如图1所示:
图1
Shape接口定义了所有几何图形都必须实现的公共方法: draw()和erase(),实现该接口的Python代码如下所示,Python中没有接口的概念,因此在具体实现时可以使用类来替代。
代码清单1:shape.py
class Shape:
# 绘制图形
def draw(self):
pass
# 擦除图形
def erase(self):
pass
Circle类是Shape的一种具体形式,它实现了Shape接口定义的所有方法,此外还添加了一个属性__radius,用来表示圆的半径。以下是实现Circle类的代码:
代码清单2:circle.py
class Circle (Shape):
def __init__(self, radius = 0):
self.__radius = radius
# 绘制圆形
def draw(self):
print "Draw Circle"
# 擦除圆形
def erase(self):
print "Erase Circle"
# 半径的取值方法
def getRadius(self):
return self.__radius
# 半径的赋值方法
def setRadius(self, radius):
self.__radius = radius
Rectangle类也是Shape的一种具体形式,它实现了Shape接口定义的所有方法,并添加了__width和__height两个属性,分别表示矩形的宽度和高度。以下是实现Rectangle类的代码:
代码清单3:rectangle.py
class Rectangle (Shape):
def __init__(self, width = 0, height = 0):
self.__width = width
self.__height = height
# 绘制矩形
def draw(self):
print "Draw Rectangle"
# 擦除矩形
def erase(self):
print "Erase Rectangle"
# 宽度的取值方法
def getWidth(self):
return self.__width
# 宽度的赋值方法
def setWidth(self, width):
self.__width = width
# 高度的取值方法
def getHeight(self):
return self.__height
# 高度的赋值方法
def setHeight(self, height):
self.__height = height
同样,Diamond类也是Shape的一种具体形式,它实现了Shape接口中定义的所有方法,并且添加了__width和__height两个属性,分别表示菱形的宽度和高度。以下是实现Diamond类的代码:
代码清单4:diamond.py
class Diamond (Shape):
def __init__(self, width = 0, height = 0):
self.__width = width
self.__height = height
# 绘制菱形
def draw(self):
print "Draw Diamond"
# 擦除菱形
def erase(self):
print "Erase Diamond"
# 宽度的取值方法
def getWidth(self):
return self.__width
# 宽度的赋值方法
def setWidth(self, width):
self.__width = width
# 高度的取值方法
def getHeight(self):
return self.__height
# 高度的赋值方法
def setHeight(self, height):
self.__height = height
所有几何图形类都定义好后,下面要做的就是提供一个"工厂"类ShapeFactory,来创建各种几何图形的具体实例。ShapeFactory类的作用就是根据外界的要求,创建出不同的几何图形对象,如圆形(Circle)、矩形(Rectangle)或菱形(Diamond),这样整个软件的体系结构就将如图2所示。
图2
ShapeFactory类用于创建各种几何图形的实例,其实现代码如下所示:
代码清单5:shapefactory.py
class ShapeFactory:
def factory(self, which):
if which == "Circle":
return Circle()
elif which == "Rectangle":
return Rectangle()
elif which == "Diamond":
return Diamond()
else:
return None
在ShapeFactory类中只定义了一个方法factory(),外界通过调用该方法,来创建其所需的几何图形对象,但如果所请求的类是系统所不支持的,则将返回None。在引入了工厂类之后,其它模块如果想生成几何图形类的实例,只需调用ShapeFactory类的factory()方法就可以了:
fac = ShapeFactory()
shape = fac.factory("Diamond")
if shape != None:
shape.draw()
就样就成功地将类是如何创建的这一实现细节向外界隐藏起来了,这就是简单工厂模式所采取的基本策略。
三、一般结构
简单工厂模式属于类的创建型模式,适合用来对大量具有共同接口的类进行实例化,它可以推迟到运行的时候才动态决定要创建哪个类的实例
本文来自: 中国IT直播室(http://www.itzbs.com)
GoF23种设计模式中创建型模式有5种,分别是:Singleton单件模式、Abstract Factory抽象工厂模式、Builder生成器模式、Factory Method工厂方法模式、Prototype原形模式。下面分别总结这几种设计模式。
设计模式 | GoF的描述 | 我的理解 |
Singleton单件模式 | 保证一个类仅有一个实例,并提供一个该实例全局的访问点 | 控制实体对象的数量 |
Abstract Factory抽象工厂模式 | 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们的具体类 | 解决一个系列的对象变化的问题 |
Builder生成器模式 | 将一个复杂对象的构建与其表示向分离,使得同样的构建过程可以创建不同的表示 | 应对项目中一些复杂对象的创建工作。所谓“复杂对象”,是指:此对象中还含有其它的子对象 |
Factory Method工厂方法模式 | 定义一个用于创建对象的接口,让子类决定实例化那个类。FactoryMethod使得一个类的实例化延迟到子类 | 解决的是“某个对象”的创建工作,由于需求的变化,这个对象常常面临着剧烈的变化,但是这个对象拥有的接口相对稳定。也就是说:枝节常常发生变化,但是枝节与主干的接口相对稳定 |
Prototype原形模式 | 使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象 | 某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口 |
在学习的过程中,觉得从功能上看Abstract Factory模式和Builder模式容易混淆,Factory Method模式和Prototype模式不好区分。Singleton模式没什么太大的困难。下面就来分析一下前四种模式。
一、Abstract Factory模式和Builder模式:
Abstract Factory是应对一系列对象的创建的问题,正如前面文章中举的例子,对于创建一个汽车对象来说,Abstract Factory模式更关注一系列的对象的创建,或者说是汽车类型中的各个部分,如:Wheel、Engine、Body等等类型的创建。换句话说关注点在这一系列对象上。
Builder是应对一个复杂对象创建的问题,或者说是针对这个复杂对象中的子对象的创建的问题。以汽车的例子来说,我觉得比起Abstract Factory模式,Builder模式相对注重汽车类型(上面所说的“复杂对象”)本身以及其各个部分(Wheel、Engine、Body等等)类型的创建。Builder模式要求这个复杂的类型(汽车)中的各个子类型的结合部分相对稳定,用例子说明就是对于汽车来说,无论用什么配件组装,个个配件的组装方式都一样,有相对稳定的接口。对于这辆车你用什么牌子的Wheel、什么牌子的Engine可能变化会很大很频繁。
二、Factory Method模式和Prototype模式:
开始我觉得这两种模式从功能上讲是一样的(个人观点),都是封装了对对象的创建,只不过Prototype模式是用原型克隆进行拷贝来完成对象的创建,在这之中还应注意浅拷贝和深拷贝的区别。在向同事请教后有点明白。这两种模式在应用场景上还是一定的区别的。
Factory Method模式是重新创建一个对象
Prototype模式是利用现有的对象进行克隆,当两个对象或多个对象雷同的时候,可以考虑用一个已创建的对象去克隆出其余的对象。