设计模式之factory method与c++反射

来源:互联网 发布:石油库存公布数据 编辑:程序博客网 时间:2024/06/17 08:20
设计模式之factory method与c++反射
-记我曾经的误解

  Factory Method的官方解释是:
  Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses
  定义一个接口(Creater)来创建一个对象(Object),但是由子类(SubCreater)来决定要实例化哪一个对象(SubObject);
  这句话相当不好理解,很长一段时间以来我都似懂非懂,括号中的注解是我加上的,这样前后区分开来,可能对于我这样笨的人比较有效。

一.设计模式能干什么
  首先,我会摘抄两个例子,分别是“简单工厂”与“工厂方法”,看看设计模式能干什么。
参考自:
http://hobe.cnblogs.com/archive/2005/10/31/265875.aspx
http://hobe.cnblogs.com/archive/2005/11/01/266749.aspx

首先定义产品类及其子类:
class VideoWiring
{
public:
    virtual string PlayVideo()=0;
}

class VCD: public VideoWiring  
{
public:
    string PlayVideo()
    {
        return "正在播放播放VCD";
    }
}

class DVD: public VideoWiring  
{
public:
    string PlayVideo()
    {
        return "正在播放播放DVD";
    }
}

1.简单工厂
class Create
{
public:
    static VideoWiring* factory(string  VideoName)
    {
        switch(VideoName)
        {
            case "DVD":
                return new DVD();
            case "VCD":
                return new VCD();
        }
        return null;
    }
}

client端代码:
void PlayVideo()
{
     VideoWiring *vw=Create.factory("DVD");
     vw->PlayVideo();
     delete vw;
     
     vw=Create.factory("VCD");
     vw->PlayVideo();
     delete vw;
}
好处是:
1、充分利用了多态性不管什么具体产品都返回抽象产品。

2、充分利用了封装性,内部产品发生变化时外部使用者不会受到影响。       

缺点是:如果增加了新的产品,就必须得修改工厂(Factory),不满足闭合原则。

2.工厂方法
class Create
{
public:
    virtual VideoWiring* factory()=0;
}

class DVDCreate: public Create
{
    VideoWiring* factory()
    {
        return new DVD();
    }
}

class VCDCreate: public Create
{
    VideoWiring* factory()
    {
        return new VCD();
    }
}
client端代码:
void PlayVideo()
{
     VideoWiring *dvd,*vcd;
     Create *dvdCreate,*vcdCreate;
    
     dvdCreate=new DVDCreate();
     dvd=dvdCreate->factory();
     dvd->PlayVideo();
     delete dvd;
    
     vcdCreate=new VCDCreate();
     vcd=vcdCreate->factory();
     vcd->PlayVideo();
     delete vcd;
}
工厂方法克服了简单工厂的缺点,增加新的产品时,不必修改现存的代码,而只需增加新代码。满足开闭原则。

二.设计模式不能干什么
  我们注意到,简单工厂中的factory方法,用了一串switch-case语句,相当的丑陋,不仅如此,正是由于无法穷举,导致简单工厂不能满足闭合性的要求,设想一下,如果存在以下的语法:
    static VideoWiring* factory(string  VideoName)
    {
        VideoWiring *pvw = CreateInstance(VideoName);
        return pvw;
    }
问题不就解决了,也就不需要后面提到的"factory method“了,实际上,这种”名称->实例"的映射,就是大名鼎鼎的“反射”,许多语言都提供的属性,可是,非常不幸,c++没有!
  所以,即便是"factory method”,也只是试图从另外一个角度去满足闭合原则,并没有解决“名称->实例"的问题。
  考虑一个实际问题,输入为一个数据流inbuffer,可以按照固定格式,分析出它的业务类型typeid,也知道每种业务类型对应的处理类handler,那么,请问:如何应用设计模式?简单工厂能够解决吗?工厂方法呢?
  我的答案是:工厂方法不行,为什么呢,因为它把”名称->实例"的映射彻底交给了client,势必在client端要写上一长串的switch-case语句,来判断某个typeid需要创建哪个create,这与简单工厂中factory方法的switch-case真的有什么实质性差别吗?我认为没有,所以,解决之道不在于设计模式,而在于反射。

三.解决之道
  对上述问题,我的解决方法是:简单工厂+反射,固然,c++中不存在反射的语法,但是,你可以通过某种手段做到类似。
参见:
http://www.cnblogs.com/jiezhi/archive/2006/07/12/448962.html
采用的是全局变量+函数指针+map的做法,可以参考。实际上就是自己创建一个有限映射集合。

四.我曾经的误解
  很长时间以来,我一直以为工厂方法是为了解决简单工厂中那个反射问题的,现在才发现不是,至少,不是正面解决,而是避开了,因为它的目标不是为了对付一个语法问题,而是为了实现开闭原则,不应该认为设计模式能够增加新的语法特性,它是为了软件的扩展性而存在的。

附:
开闭原则就是一个软件实体在扩展性方面应该是开放的而在更改性方面应该是封闭的
0 0
原创粉丝点击