“设计模式”学习之二:单件、原型与生成器模式

一、单件(Singleton)

1、引言

C++中如何创建一个唯一的对象或实例?全局变量是一种,更好的替代方式是单件模式。

当某系统只能有一个**时,应该想到该模式。比如,系统中只有一个文件系统、打印机。

 

2、思路

图中,_instance用以记录唯一实例;GetInstace()用以返回_instance实例。

 


3、典型代码

(1)将Singleton类构造函数声明为private(更安全)或protected(当需要被继承时),故Singleton类不可以在外部被实例化。

(2)Singleton*Singleton::_instance = 0; //在.cpp中初始化

(3)在GetInstance()实现中:

if(_instance == 0)   _instance = newSingleton();  //惰性Lazy初始化方法

return_instance;

(4)在main客户代码中:

Singleton*sgn = Singleton::GetInstance();

 

4、应用提示

(1)对于多线程程序,存在一种可能性——重复创建问题:对GetInstance()的调用同时发生,那么C++中将发生内存泄露。这时可以使用单件模式的变种——双重检查锁定Double-Checked Locking模式(该方法对JAVA无效):在“==0”检查之后进行同步,然后再次检查“==0”以确保实例尚未被创建。代码如下:

              class Singleton

              {

                             staticSingleton * _instance;

                             Singleton();

                  public:

static Singleton*GetInstance();

              }

Singleton*Singleton::_instance = 0;

Singleton*Singleton:: GetInstance()

{

if (_instance == 0)

{

              //do sync here进行同步操作

if (_instance == 0)

_instance = newSingleton();

             }

return _instance;

}

(2)当Singleton存在多个子类时,有两种方式完成运行时决定实例化哪个子类:一是,在Singleton的GetInstance()实现中进行if判断(默认是new Singleton);另一种更灵活的方法是使用一个单件注册表(registry of singleton)——基类必须实现注册表功能

(3)《Head First》提到:“如果你的程序出现大量单件,那么你可能需要好好检查你的设计。因为通常适用使用单件模式的机会不多。”

 

二、原型(Prototype)

1、引言

抽象工厂模式中提到过,对于童装和成人装,需要设立不同的具体工厂来生产。若要新上一个老年装系列产品,可以考虑重新设厂,但更经济的做法如下:复制成人装工厂的各条产线,通过微调初始化生产参数,从而完成老年装的生产。

2、思路

原型模式,是在一个既成实例基础上,拷贝创建新的对象。典型思路如下图。当中可能需要应用一个独立的Initialize()函数来重新初始化拷贝过来的对象内部状态。

 


3、典型代码

(1)在具体类ConcretePrototype1/2中声明:

ConcretePrototype(constConcretePrototype& cp); //拷贝构造函数

Prototype*Clone() const;

(2)在Clone()实现中,return new ConcretePrototype(*this);

(3)在客户main()中,

Prototype*p = new ConcretePrototype();

Prototype*p1 = p->Clone();

 

4、应用提示

(1)原型模式中,最困难的部分在于如何正确实现Clone()。C++中提供了拷贝构造函数,典型代码中,用了编译器缺省方式(按位拷贝/按成员拷贝),即两个对象共享指针。为了使复制对象和原对象保持相对独立性,需要进行深拷贝。关注“深拷贝”和“浅拷贝”的区别。

(2)该模式的主要缺陷是需要每一个Prototype子类都实现Clone操作。

(3)除了和工厂方法的竞争和协同关系之外,大量使用组成Composite模式和装饰Decorator模式的设计通常会用到原型模式。

 

三、生成器(Builder)

1、引言

作为一个现代化的成熟汽车厂商,需要向市场推出几款车型以适应不同的消费群体。为了构造某一款车,需要在生产的各个阶段(如发动机生产、车身外观设计、底座设计等等)给定不同的生产参数,当然这个工程会非常庞大复杂。而作为一个成熟的体系,应当将构建的机制隐藏在底层车间,当顾客需要某款车时,只需要跟总体部沟通,由它向各车间传达一些参数即可向顾客呈现所需车型。Builder模式就是为了将复杂对象的构建与展示分离,使得同样的构建过程可以有不同的展现;当中的导向器Director就好比总体部,负责调度构造使用生成器的接口。

 

2、思路

作为客户,需要创建Director对象,同时配置所需的Builder对象。然后,导向器Director会利用一个函数Construct()通知具体生成器ConcreteBuilder完成各阶段构造工作。最后,客户从ConcreteBuilder中获取产品。

 


3、典型代码

(1)Director类声明:

Director(Builder*bld);   //构造函数

Private:  Builder* _bld; 

VoidConstruct();

(2)在Director()构造函数实现中:  _bld= bld;

(3)在Construct()实现中:

_bld->BuildPartA("user-defined");

_bld->BuildPartB("user-defined");

(4)ConcreteBuilder类声明:  BuildPartA/B("user-defined")以及  Product*GetProduct();

(5)在GetProduct()实现中:    returnnew Product();

(6)在客户main()中:

Director*d = new Director(new ConcreteBuilder());

d->Construct();

Product*p1 = (*d). _bld->GetProduct();

4、应用提示

(1)一般来说Builder模式中对象不是直接返回的,它强调一步步构建复杂对象,运用相同的构造过程创建不同的对象(可能是通过Construct()函数传入上述参数"user-defined"来实现),由客户来通过调用ConcreteBuilder从而获取Product对象。

(2)Builder模式和Abstract Factory模式都用于复杂对象的创建。但侧重点不同,前者强调一步步的创建过程;后者强调一系列相关对象的创建。

(3)组成Composite模式通常是用Builder生成的。

 

猜你喜欢

转载自blog.csdn.net/vison20080808/article/details/6630238