001.设计模式之Simple Factory模式

来源:互联网 发布:信捷plc编程步进梯形图 编辑:程序博客网 时间:2024/05/16 10:30

场景:

用户想从一个目的地A到达目的地B, 于是选择了使用飞机, 但是用户只是使用飞机的功能(Fly), 不代表要制造飞机, 于是就有一个飞机工厂负责制造飞机.

现在有一个飞机工厂, 可以制作直升飞机, 游泳飞机, 超音速飞机 3种飞机..

3种飞机的共同特性就是可以飞Fly,  Fly的结果就是飞到指定目的地, Fly的体现不同.

直升飞机 :        普通速度飞行,垂直升降(特殊功能).

游泳飞机:          水上飞行, 潜水(特殊功能).

超音速飞机:  快速飞行, 超音速飞行(特殊功能).

使用

1. 用户A(直升飞机师)说我要从越秀山飞到白云上, 于是用户A就对飞机工厂说 我要一架直升飞机, 工厂给了用户一架直升飞机, 用户使用直升飞机的飞行功能(普通速度飞行)飞行到目的地, 并且使用了直升飞机的特殊功能(垂直升降).

2. 用户B(游泳飞机师)说我要从湛江飞到海南岛, 于是用户B就对飞机工厂说 我要一架游泳飞机, 工厂给了用户一架游泳飞机, 用户使用游泳飞机的飞行功能(水上飞行)飞行到目的地, 并且使用了游泳飞机的特殊功能(潜水).

3. 用户C(超音速飞机)说我要5分钟内从广东飞到台湾, 于是用户C就对飞机工厂说 我要一架超音速飞机, 工厂给了用户一架超音速飞机, 用户使用超音速飞机的飞行功能(水上飞行)飞行到目的地, 并且使用了超音速飞机的特殊功能超音速飞行).

4. 用户D(直升飞机师)Shit, 我就讨厌用户B可以去海南岛, 又可以驾驶飞机潜水, 我也要从湛江飞到海南岛, 我也要潜水,于是用户D就对飞机工厂说 我要一架直升飞机(对应的飞机师只能使用对应的飞机), 工厂给了用户一架直升飞机, 用户使用直升飞机的飞行功能. 本来使用直升飞机的飞行功能是可以从湛江飞到海南岛的, 但用户D说我也要潜水. 结果用户D就挂了.(用直升飞机潜水你说挂不挂)

5. 用户E(太空飞机师)说我要去火星, 于是用户E就对飞机工厂说 我要一架太空飞机, 但是飞机工厂生产不了太空飞机, 飞机工厂只能惋惜的对用户E说我们生产不了太空飞机, 对不起.

6. 飞机工厂心里想 Shit, 生产不了太空飞机, 有钱都赚不了. 于是飞机工厂就研发了太空飞机. 由于研发了太空飞机, 飞机工厂的经营范围就扩大了, 于是被工商部门要求更换营业执照(执照号变了). 由于执照号变了, 所以用户来买飞机时, 购买的流程并没有变化, 但是要更换一下订单(订单上的执照号变了, 其他的都没有变).

 

说明:

Simple Factory模式(又称Static Factory模式),一个Simple Factory生产成品,而对客户端隐藏产品产生的细节。实作时定义一个产品介面(interface),并透过特定静态方法来建立成品。 就是各种有共同特性, 又有各自特性的对象集中在一个地方创建, 用户通过参数来申请自己需要的对象, 对于对象特有的特性, 用户使用类型转换来使用.

 

 

代码:

// 飞机抽象类

class CPlane

{

public:

     CPlane(){};

     virtual ~CPlane(){};

     virtual void Fly() = 0;

};

 

// 游泳飞机

class CSwimPlane : public CPlane

{

public:

     CSwimPlane();

     virtual ~CSwimPlane();

     virtual void Fly();

     void Dive();

};

 

// 直升飞机

class CHolicopter : public CPlane

{

public:

     CHolicopter();

     virtual ~CHolicopter();

     virtual void Fly();

     void VerticalUpDown();

};

 

// 超音速飞机

class CSoundPlane : public CPlane

{

public:

     CSoundPlane();

     virtual ~CSoundPlane();

     virtual void Fly();

     void SoundFly();

};

 

// 飞机的类型

const int PLANE_TYPE_HOLICOPTER      = 0;

const int PLANE_TYPE_SWIMPLANE       = 1;

const int PLANE_TYPE_SOUNDPLANE      = 2;

class CPlaneFactory

{

public:

     static CPlane* CreatePlane(const int nPlaneType)

{

     switch(nPlaneType)

     {

     case PLANE_TYPE_HOLICOPTER:

         return new CHolicopter;

     case PLANE_TYPE_SWIMPLANE:

         return new CSwimPlane;

     case PLANE_TYPE_SOUNDPLANE:

         return new CSoundPlane;

     }

     std::cout << "对不起没有你想要的飞机" << std::endl;

     return 0;

}

};

 

// 调用

     CPlane* pPlane = 0;

     // 用户A

     // 申请一架直升飞机

     pPlane = CPlaneFactory::CreatePlane(PLANE_TYPE_HOLICOPTER);

     // 使用直升飞机的飞行功能

     pPlane->Fly();             

     // 使用直升飞机的垂直升降功能

     static_cast<CHolicopter*>(pPlane)->VerticalUpDown();

     delete pPlane;

 

     // 用户B

     // 申请一架游泳飞机

     pPlane = CPlaneFactory::CreatePlane(PLANE_TYPE_SWIMPLANE);

     // 使用游泳飞机的飞行功能

     pPlane->Fly();             

     // 使用直升飞机的潜水功能

     static_cast<CSwimPlane*>(pPlane)->Dive();

     delete pPlane;

 

     // 用户C

     // 申请一架超音速飞机

     pPlane = CPlaneFactory::CreatePlane(PLANE_TYPE_SOUNDPLANE);

     // 使用超音速飞机的飞行功能

     pPlane->Fly();             

     // 使用超音速飞机的超音速飞行功能

     static_cast<CSoundPlane*>(pPlane)->SoundFly();

     delete pPlane;

 

     // 用户E

     // 申请一架太空飞机

     pPlane = CPlaneFactory::CreatePlane(4);

     // 飞机工厂生产不了太空飞机

     if(pPlane)

     {

         pPlane->Fly();             

         delete pPlane;

     }

 

     // 用户D

     // 申请一架直升飞机

     pPlane = CPlaneFactory::CreatePlane(PLANE_TYPE_HOLICOPTER);

     // 使用直升飞机的飞行功能

     pPlane->Fly();             

     // 使用直升飞机潜水, 飞机师挂掉了!!!!!!!!!

     static_cast<CSwimPlane*>(pPlane)->Dive();

     delete pPlane;

 

 

     // 在飞机工厂增加了生产太空飞机时

     // 各个用户使用CPlaneFactory的代码不需要改变, 因为使用流程没有变

     // (还是CPlaneFactory::CreatePlane), 但是需要重新编译一次, 因为

     // CPlaneFactory::CreatePlane的实现改变了(动态夹杂CPlaneFactory::CreatePlane的除外).

源码: 001SimpleFactory.rar

http://download.csdn.net/source/2808048

总结:

1. Simple Factory模式涉及到三个角色

A. 工厂类角色:负责创建产品的对象。如上面的CPlaneFactory类。它是工厂方法模式的核心。它往往由一个具体的类实现。

B. 抽象产品角色:实现了产品的共同接口,它可以由抽象类或接口实现。如上面的CPlane

C. 具体的产品:某一具体的产品,如上面的CHolicopter, CSwimPlane, CSoundPlane

 

2. Simple Factory模式的应用

Simple Factory模式是为了将具体子类实例化的工作隐藏起来,从而客户端不必考虑如何将具体子类实例化,因为抽象类CPlaneFactory会提供它的合适的具体子类的实例。这是一个简单工厂方法模式的绝佳应用。

利用具体产品类的超类类型将它的真实类型隐藏起来,其好处是提供了系统的可扩展性。如果将来有新的具体子类被加入到系统中来,那么工厂类可以将交给客户端的对象换成新的子类的实例,而对客户端没有任何影响(调用流程上)

这种将工厂方法的返还类型设置成抽象产品类型的做法,叫做针对抽象编程,这是依赖倒转原则(DIP)的应用。

 

3. Simple Factory模式的缺点

大家不难看出,如果新增加产品如:太空飞机,则需要修改工厂类(CPlaneFactory),从而限制了其灵活性;而对于产品角色类适合,因此简单工厂只在有限的程度上支持“开–闭”原则。

工厂类集成了所有的创建工作,显得工厂类负任比较重,万一出问题,所有的创建工作将不能进行。当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展时较为困难。

这一缺点在Factory Method模式中得到克服。

由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此,工厂角色无法形成基于继承的等级结构。这一缺点会在Factory Method模式中得到克服。

 

项目应用

自己工作中遇到这样的需求: 使用热敏打印机打印出指定内容的小票, 打印内容当然是动态的. 分析热敏打印机的特性无非就是打印, 走纸, 切纸, 设置打印字体, 打印图片这几个动作. 而打小票的流程就是打标题, 走纸, 打内容,  打图片, 走纸, 切纸.

打印机的特性和打小票的流程都是固定的了, 但最大的问题就是各种打印机的打印指令有可能不同.

于是设计了一个抽象打印机类, 抽象打印机类中的接口就是打印, 走纸, 切纸, 设置打印字体, 打印图片等. 各种品牌的打印机分别定义一个实现类. 同时定义了一个打印机生成类.

在系统加载的时候, 就使用打印机生成类根据打印机的类型创建指定打印机对象.

如果以后增加的打印机类型, 那就在打印机的生成类中增加该打印机对象的创建代码.

重新编译即可.

 

这里就是明显的不足就是增加了打印机类型就要修打印机生成类.(把这些放到一个DLL, 只编译DLL也可以.)

引用:

http://www.riabook.cn/doc/designpattern/SimpleFactory.htm

http://agio.javaeye.com/blog/202634

 

原创粉丝点击