设计模式之创建型模式

《设计模式:可复用面向对象软件的基础》第三章 创建型模式

一、 ABSTRACT FACTORY (抽象工厂)

1.意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

2.适用情况

  • 一个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要有多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

3.结构

设计模式之创建型模式

4.优缺点

1)它分离了具体的类  Abstract Factory模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。客户通过它们的抽象接口操作实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。

2)它使得易于交换产品系列  一个具体工厂类在一个应用中仅出现一次——即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置。这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。

3)它有利于产品的一致性  当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而Abstract Factory很容易实现这一点。

4)难以支持新种类的产品  难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变。

5.实现中的一些有用技术

1)将工厂作为单件  一个应用中一般每个产品系列只需一个ConcreteFactory的实例。因此工厂通常最好实现为一个Singleton。

2) 创建产品  AbstractFactory仅声明了一个创建产品的接口,真正创建产品是由ConcreteProduct子类实现的。最通常的一个办法是为每一个产 品定义一个工厂方法。一个具体的工厂将为每个产品重新定义该工厂方法一指定产品。虽然这样的实现很简单,但它却要求每个产品系列都要有一个新的具体工厂子 类,即使这些产品系列的差别很小。

    如果有多个可能的产品系列,具体工厂也可以使用Prototype模式来实现。具体工厂使用产品系列每一个产品的原型实例来初始化,且它通过复制它的原型来创建新的产品。在基于原型的方法中,使得不是每个新的产品系列都需要一个新的具体工厂类。

3) 定义可扩展的工厂  AbstractFactory通常为每一种它可以生产的产品定义个操作。产品的种类被编码在操作型构中。增加一个新的产品要求改变 AbstractFactory的接口以及所有与它相关的类。一个更灵活但不太安全的设计是给创建型对象的操作增加一个参数。该参数指定了将被创建的对象 的种类。它可以是一个标识符、一个整数、一个字符串,或其他任何可以标识这种产品的东西。

 6.相关模式

AbstractFactory类通常用工厂方法(Factory Method)实现,但它们也可以用Prototype实现。

一个具体的工厂通常是一个单件(Singleton)。

 

二、BUILDER(生成器)

1.意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

2.适用情况

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构造过程必须允许被构造的对象有不同的表示时。

3.结构

设计模式之创建型模式

4.特点

1)它可以改变一个产品的内部表示  Build对象提供给导向器一个构造产品的抽象接口。该接口使得生成器可以隐藏这个产品的表示和内部结构。它同时也隐藏了该产品是如何装配的。因为产品通过抽象接口构造的,你在改变产品的内部表示时所要做的只是定义一个新的生成器。

2) 它将构造代码和表示代码分开  Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息;这些类是不出现在 Builder接口中的。每个Concrete Builder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同 的Product。

3)它可使你对构造过程进行更精细的控制  Builder模式与一下子就生成产品的创建型模式不同。它是可以在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回它。因此 Builder接口比其他创建型模式能更好的反映产品的构造过程。这使你可以更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。

5.实现

    通常有一个抽象的Builder类为导向者可能要求创建的每一个构件定义一个操作。这些操作缺省情况下什么都不做。一个ConcreteBuilder类对他有兴趣创建的构件重定义这些操作。

这里是其他一些要考虑的实现问题:

1)装配和构造接口  生成器逐步的构造它们的产品。因此Builder类接口必须足够普遍,以便为各种类型的具体生成器构造产品。

2)为什么产品没有抽象类  通常情况下,由具体的生成器生成的产品,它们的表示相差是如此之大以至于给不同的产品以公共的产品以公共父接口没有太大意思。

3)在Builder中缺省的方法为空  C++中,生成方法故意不声明为纯虚函数,而是把它们定义为空方法,这使客户只重定义他们感兴趣的操作。

6。相关模式

Abstract Factory与Builder相似,因为它也可以创建复杂对象。主要的区别是Builder模式着重与一步步构造一个复杂对象。而Abstract Factory着重于多个系列的产品对象(简单的或是复杂的)。Builder在最后一步返回产品,而对于Abstract Factory来说,产品是立即返回的。

Composite通常是用Builder生成的。

 

三、FACTORY METHOD(工厂方法)

1.意图

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

2.适用情况

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望它的子类来指定它所创建的对象的时候。
  • 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部花的时候。

3.结构

设计模式之创建型模式

4.特点

工厂方法不再将与特定应用有关的类绑定到你的代码中。代码仅处理Product接口;因此它可以与用户定义的任何ContreteProduct类一起使用。

工 厂方法的一个潜在缺点在于客户可能仅仅为了创建一个特定的ConcreteProduct对象,就不得不创建Creator的子类。当Creator子类 不必需时,客户现在必然要处理演化的其他方面;但是当客户无论如何必须创建Creator的子类时,创建子类也是可行的。此外还有:

1)为子类提供挂钩(hook)  用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。Factory Method给子类的一个挂钩以提供对象的扩展版本。

2)连接平行的类层次  迄今为止,在我们所考虑的例子中,工厂方法并不往往只是被Creator调用,客户可以找到一些有用的工厂方法,尤其在平行类层次的情况下。     当一个类将它的一些职责委托给一个独立的类的时候,就产生了平行类层次。

5.实现

当应用Factory Method模式时要考虑下面一些问题:

1) 主要有两种不同的情况  Factory Method模式主要有两种不同的情况:a)第一种情况是,Creator类是一个抽象类并且不提供它所声明的工厂方法的实现。b)第二种情况 是,Creatro是一个具体的类而且为工厂方法提供一个缺省的实现。也有可能有一个定义了缺省实现的抽象类,但这不太常见。

    第一种情况需要子类来定义实现,因为没有合理的缺省实现。它避免了不得不实例化不可预见类的问题。第二种情况中,具体的Creator主要因为太灵活才使 用工厂方法。它所遵循的准则是,“用一个独立的操作创建对象,这样子类才能重定义它们的创建方式。”这条准则保证恶劣子类的设计这能够在必要的时候改变子 类所实例化的对象的类。

2)参数化工厂方法  该模式的另一种情况是的工厂方法可以创建多种产品。工厂方法采用一个标识要被创建的对象种类的参数。工厂方法创建的所有对象将共享Product接口。

3)特定一样的变化和问题  不同的一样有助于产生其他一些有趣的变化和警告。

4)使用模板以避免创建子类  正如我们已经提及的,工厂方法另一个潜在的问题是它们可能仅为了创建适当的Product对象而迫使你创建Creator子类。在C++中另一个解决办法是提供Creator的一个模板子类,它使用Product类作为模板参数。

5)命名约定  使用命名约定是一个好习惯,它可以清楚地说明你正在使用工厂方法。

6.相关模式

Abstract Factory经常用工厂方法实现。

工厂方法通常在Template Methods中被调用。

Prototype不需要创建Creator的子类。但是,它们通常要求针对Product类的Initialize操作。Creator使用Initialize来初始化对象。而Factory Method不需要这样的操作。

 

四、PROTOTYPE(原型)

1.意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

2.适用情况

  • 当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者
  • 为了避免创建一个与产品类层次平行的工厂类层次时;或者
  • 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

3.结构

设计模式之创建型模式

4.特点

Prototype有许多和Abstract Factory和Builder一样的效果:它对客户隐藏了具体的产品类,因此减少恶劣客户知道的名字的数目。此外,这些模式使客户无需改变即可使用与特定应用相关的类。

下面列出Prototype模式的另外一些优点。

1)运行时刻增加和删除产品  Prototype允许只通过客户注册原型实例就可以将一个新的具体产品类并入系统。它比其他创建型模式更为灵活,因为客户可以在运行时刻建立和删除原型。

2)改变值以指定新对象  高度动态的系统允许你通过对象符合定义新的行为——例如,通过为一个对象变量指定值——并且不定义新的类。你通过实例化已有类并且将这些实例注册为客户对象的原型,就可以有效定义新类别的对象。可以可以将职责代理给原型,从而表现出新的行为。

3)改变结构以指定新对象  许多应用由部件和子部件来创建对象。通过实例化复杂的、用户定义的结构,重复使用该结构。

4) 减少子类的构造  Factory Method经常产生一个与产品层次平行的Creator类层次。Prototype模式使得你克隆一个原型而不是请求一个工厂方法产生一个新的对象。因 此你根本不需要Creator类层次。这一有点主要适用于像C++这样不将类作为一级类对象的语言。

5)用类动态配置应用  一些运行时刻环境允许你动态将类装载到应用中。在像C++这样的一样中,Prototype模式是利用这种功能的关键。

    Prototype的主要缺陷是每一个Prototype的子类都必须实现Clone操作,这可能很困难。例如,当考虑的类已经存在时就难以新增Clone操作。当内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能也会很困难的。

5.实现

当实现原型时,需要考虑下面一些问题:

1)使用一个原型管理器  当一个系统中原型数目不固定时(也就是说,它们可以动态创建和销毁),要保持一个可用原型的注册表。客户不会自己来管理原型,但会在注册表中存储和检索原型。客户在克隆一个原型前会向注册表请求该原型。我们称这个注册表为原型管理器。

2)实现克隆操作  Prototype模式最困难的部分在于正确实现Clone操作。当对象结果包含循环引用时,这尤为棘手。、

3) 初始化克隆对象  当一些客户对克隆对象已经相当满意时,另一些客户将会希望使用他们所选择的一些值来初始化对象的一些或是所有的内部状态。一般来说不可能在Clone操作 中传递这些值,因为这些值的数目由于原型的类的不同而会有所不同。一些原型可能需要多个初始化参数,令一些可能什么也不要。在Clone操作中传递参数会 破坏克隆接口的同一性。

6.相关模式

Prototype和Abstract Factory模式在某种方面是相互竞争的。但是它们也可以一起使用。Abstract Factory可以存储一个被克隆的原型的集合,并且返回产品对象。

大量使用Composite和Decorator模式的设计通常也可从Prototype模式处获益。

 

五、SINGLETON(单件)

1.意图

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2.适用情况

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

3.结构

设计模式之创建型模式

4.特点

1)对唯一实例的受控访问  因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。

2)缩小名空间  Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。

3)允许对操作和表示的精化  Singleton类可以有子类,而且用这个扩展类的实例类来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。

4)允许可变数目的实例  这个模式使得你易于改变你的想法,并允许访问Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变。

5)比类操作更灵活  另一种封装单件功能的凡是使用类操作。

5.实现

下面是使用Singleton模式时所要考虑的实现问题:

1)保证一个唯一的实例

2)创建Singleton类的子类   主要问题与其说是定义子类不如说是建立它的唯一实例,这样客户就可以使用它。

 

六、创建型模式总结

    用一个系统创建的那些对象的类对系统进行参数化有两种常用方法。一种是生成创建对象的类的子类;这对应于使用Factory Method模式。这种的主要缺点是,仅为了改变产品类,就可能需要创建一个新的子类。这样的改变可能是级联的。例如,如果产品的创建者本身是有一个工厂 方法创建的,那么你也必须重定义它的创建者。

    另一种对系统进行参数化的方法更多的依赖于对象复合:定义一个对象负责明确产品对象的类,并将它作为该系统的参数。所有这三个模式都涉及到创建一个新的负 责创建产品对象的“工厂对象”。Abstract Factory由这个工厂对象产生多个类的对象。Builder由这个对象使用一个相对复杂的协议,逐步创建一个复杂产品。Prototype由该对象通 过拷贝原型对象来创建产品对象。在这种情况下,因为原型负责返回对象,所以工厂对象和原型是同一个对象。

原文链接: https://www.cnblogs.com/arcticant/archive/2013/03/17/2964240.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    设计模式之创建型模式

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/80986

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午7:51
下一篇 2023年2月9日 下午7:51

相关推荐