设计模式随笔(二):工厂方法(Factory Method)

来源:互联网 发布:知羽电子相册模板 编辑:程序博客网 时间:2024/06/01 11:45

工厂方法(Factory Method

 

作者:Will LeeQQ31940767EMailw.lee@live.cn

声明:本文可用于个人学习、参考,未经本人授权严禁用于商业用途。有朋友转载或引用本文请注明作者和出处,谢谢!!

 

1          模式简介

工厂一般是搞生产的,方法是程序中的“操作”;工厂方法,是用于生产(对象)的操作?

这么简单,也能算作一种设计模式??

 

上面的说法,其实只说了Factory Method的一半功效,还有一半:不是简单创建对象,Factory Method可以将创建对象的具体操作从父类延迟到子类。父类只是做做样子(声明一个创建对象的接口),告诉客户程序(Client):我能创建XXX对象!其实偷偷将真正的创建操作都交由儿子去做……

 

如果你想动态的创建对象,如果你想让客户程序不依赖于具体对象(包括创建该具体对象的行为),说白一点,如果你想把创建具体对象的操作从父类延迟到子类,那么Factory Method是你的不二选择,^^

 

2          模式结构

Factory Method模式结构如图1所示:

 

 

1 Factory Method模式结构

参与模式的角色有以下几个:

1.       Product产品:Client要使用的产品。有时候,同一类型的产品又分不同的具体类型(小类型),比如同样是自行车,也有山地车、公路车、中性车之分。为避免Client面对这些五花八门的具体类手忙脚乱,此处对产品进行抽象,Client仅面向抽象Product类,并不需要了解具体Product类细节,这样Client和具体产品就没多大关系啦(专业上成为解耦,-__-)。

2.       Creator创建器,用于创建产品类对象。和Product一样的考虑,Creator也划分为抽象CreatorConcreteCreator两个类层次,抽象Creator类声明创建产品的接口,ConcreteCreator去实现这些接口。

3.       Client客户:ProductCreator的客户程序。Client使用Creator创建Product,然后使用Product提供的功能操作。

 

3          核心思想

Factory Method可以用这样几句话来概括其核心思想:

抽象Creator创建抽象Product,具体Creator创建具体Product,客户不面向具体,统一面向抽象;

抽象Creator提供HOOK方法(即本文主人公:工厂方法),供具体Creator实现,实现的是具体产品的创建操作。

运行时刻,Client使用的其实是ConcreteCreator,创建的也是ConcreteProduct,但Client并不知道这些,她并不清楚使用的是哪个ConcreteCreatorConcreteProduct,因为她仅理解抽象Creator接口和抽象Product接口。

 

Factory MethodOCPOpen-Closed Principle)和DIPDependence Inversion Principle)两大设计原则的完好应用(关于OCPDIP,参见我关于面向对象设计原则写的一篇文章)。

 

4          实现关键点

使用C++实现Factory Method时,需要注意以下问题:

1.         如何定义Factory Method

一般将Factory Method声明为虚函数(virtual function),并提供一种缺省实现:

class Creator

{

public:

Creator()

{

}

virtual ~Creator()

{

}

public:

virtual Product * CreateProduct()

{

    return NULL;

}

};

也可以将虚函数强化为纯虚函数,强制子类去实现该方法。

 

2.         如何减少Creator对象规模?

使用Factory Method,为了创建一个ConcreteProduct,通常就要创建一个对应的ConcreteCreator,这样会导致对象泛滥(Creator对象太多)。我们一般的对策是,给工厂方法提供一个参数(指明创建哪一种ConcreteProduct),让Factory Method能够创建多种具体的对象,以此减少ConcreteCreator对象开销。

 

3.         还有一种方法减少ConcreteCreator的代码书写规模:使用模板(代码复用的利器哦~)。

class Creator

{

public:

Creator()

{

}

virtual ~Creator()

{

}

public:

    virtual Product * CreateProduct() = 0;

};

 

template <typename TheProduct>

class ConcreteCreator : public Creator

{

public:

ConcreteCreator()

{

}

virtual ~ConcreteCreator()

{

}

public:

    virtual Product * CreateProduct();

};

 

template <typename TheProduct>

Product * ConcreteCreator<TheProduct>::CreateProduct()

{

    return new TheProduct;

}

这样,为一种新的ConcreteProduct定义一种ConcreteCreator的时候,就不用重新书写一个新类了,仅需要使用ConcreteCreator<typename TheProduct>实例化一个类即可。

 

模板并不能减少运行时刻对象的规模,它减少的仅是代码的写作规模和代码在内存中的存储开销。

 

5          相关设计模式

Abstract FactoryTemplate Method两种模式和Factory Method走的比较亲近,不过区分它们也很简单:

1.         Factory MethodAbstract Factory的区别:

简单的说,Abstract Factory使用并扩展了Factory Method二者都可以将具体对象的创建从父类延迟到子类,只不过Factory Method是对单个类型产品的创建,而Abstract Factory则是对一系列(多种类型)产品对象的创建(参见后续我关于Abstract Factory的随笔)。

 

2.         Factory MethodTemplate Method的区别:

二者实现手法类似,但出发点不同。都是通过HOOK方法,将一些操作延迟到子类来完成,但Factory Method出发点是为了创建对象,延迟到子类实现的是对象创建操作,而Template Method则没有这样的限制,它延迟到子类的操作可以是任何类型的操作(参见我关于Template Method的论述),Template Method主要目的是代码复用。从代码复用这点来看,Template Method有点“从下到上”的意思,将公共操作迁移到父类实现,和Factory Method“从上到下”的设计思想迥异。

 

6          设计样例

代码样例在上述描述中体现的差不多了,仅需要大家结合自己行业的具体场景,套用而已。

 

 

原创粉丝点击