阿Sam的设计模式学习笔记----Factory模式(之Factory Method)

二、Factor Method 
简单工厂的扩展性比较差,如果要得到一个新的产品,必须修改工厂。因此,我们可以把工厂也给抽象一把,提供生产的接口,将具体生产过程放到“具体的工厂”去。
  
  

1.         功能:定义一个用于创建对象的工厂接口,让实例化类的工作在子类中完成。

2.         基本思想:在抽象父类中声明用来创建对象的方法接口,而具体子类(具体的工厂)通过覆盖接口方法实现对对象的创建过程和初始化。

3.         使用情况:

一个类不(需要)知道它所必须创建的类;

一个类希望由它的子类来指定所创建的对象;

类将创建对象的职责委托给多个帮助子类中的某一个,并希望指定某个帮助子类时。

4.         案例举例:组件对象模型(COM)中常用!

5.         结构

6.代码示例:

还是以前面的手机为例。Mobile, NokiaPhoneMotoPhone三个类没有变化。

A. 建立工厂类(Factory),注意,这个工厂是抽象的。本例中就是卖手机的柜台(Counter)

class  Counter
{
public
:
    virtual Mobile 
* getPhone() {return
 NULL;}
    virtual 
void returnPhone(Mobile * phone) {if
 (phone) delete phone;}
};

 

B.两个产品各自有各自的柜台

class NokiaCounter : public  Counter
{
    Mobile 
* getPhone() {return (new
 NokiaPhone());}
};
class MotoCounter : public
 Counter
{
    Mobile 
* getPhone() {return (new
 MotoPhone());}
};

 

C.现在偶们的客户要买手机了:

int  main()
{
    Counter 
* nokiaCnter = new
 NokiaCounter();
    Counter 
*motoCnter = new
 MotoCounter();

    Mobile 
* nokia = nokiaCnter->
getPhone();
    Mobile 
* moto = motoCnter->
getPhone();

    nokia
->
call();
    nokia
->
shortMsg();
    moto
->
call();
    moto
->
shortMsg();

    
// 手机坏了......

    nokiaCnter-> returnPhone(nokia);
    motoCnter
->
returnPhone(moto);
    
return 0
;
}

 

 

总结:

1,  Factory Method实际上是把Simple Factory中的工厂进行抽象化,在抽象类中仅仅提供接口。具体工厂继承抽象的工厂类,根据具体的产品实现/覆盖接口。

2,  如果想要添加一个产品,只需要从抽象产品类中继承并实现一个具体的产品类,然后再对这个产品实现一个具体工厂,对原有的工厂不需要任何修改,符合“开放-封闭”原则(开放-封闭原则:软件实体(类,模块,函数等等)应该是可以扩展的,但是不可修改的)

3,  Factory Method退化后就成了Simple Factory。比如说只有一个产品工厂的情况下。

4,  不足之处在于,每个具体的产品都需要引入一个对应的工厂类。例如如果需要新增加一个商品SonyEricsson,就必须增加一个柜台SonyEricssonCnter。对于这个问题,可以采用模板方法来解决:

template  < class  T >
class  CounterTemplate
{
public :
    T 
*  getPhone();
    
void  returnPhone(T  * pT);
};
template 
< class  T >  
T
*  CounterTemplate < T > ::getPhone()
{
    
return  ( new  T());
}
template
< class  T >  
void  CounterTemplate < T > ::returnPhone(T  *  pT)
{
    
if  (pT)
        delete pT;
}
//  客户端
int  main()
{
    cout 
<<   " Try to use template! "   <<  endl;
    CounterTemplate
< NokiaPhone >  nokiaFactory;
    Mobile 
* nokia  =  nokiaFactory.getPhone();
    nokia
-> call();
    nokia
-> shortMsg();
    CounterTemplate
< MothoPhone >  motoFactory;
    Mobile 
* moto  =  motoFactory.getPhone();
    moto
-> call();
    moto
-> shortMsg();
    
    
//  这个地方需要把父类对象转换为子类对象,感觉有点不爽
    
//  希望高手们路过时,指出弊端及建议!谢谢!
    nokiaFactory.returnPhone(static_cast < NokiaPhone  *>  (nokia));
    motoFactory.returnPhone(static_cast
< MotoPhone  *> (moto));
    
return   0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值