关闭

Abstract Factory

561人阅读 评论(0) 收藏 举报

 Object Factory用以生成一个对象,Abstract Factory用以生成多个关联的对象。

对于Abstract Factory而言,它有两个问题造成耦合度太高。一是Abstract Factory必须知道所有Abstruct Product,具体工厂必须知道它要生成的所有具体类。

Loki的AF解决了这个问题,在这里,我关心它如何做到的。

对于AF的抽象接口,Loki如此处理:

template    <class T>
class    AFUnit
{
public:
    
virtual    T*    DoCreate(Type2Type<T>)    = 0;
    
virtual    ~AFUnit();
}
;

你可能需要生成好几个类,但这没有问题,GenScatterHierarchy可以把这个类应用于所有的TList成员类型。明显,不同的类有不同的DoCreate方法,为了获得正确的函数调用,这个Type2Type必不可少。

Loki使用了极具威力的TypeList传递待生成的类信息:

template
<
    
class    TList,
    template    
<class>    class    Unit    = AFUnit
>
class    AbstractFactory    :public GenscatterHierarchy<TList,Unit>
{
public:
    typedef    TList    ProductList;
    template    
<class T>
    T
*    Create()
    
{
        Unit
<T>&    unit    = *this;
        
return    unit.DoCreate(Type2Type<T>());
    }

}
;

好极了,GenscatterHierarchy可以把Unit应用于每个TList中的类型。对于特定的类型T,使用特定的Unit的Docreate方法生成。其实Create是一个分派器,对于特定的类型通过它你可以获得对应的产品。在这种情况下,你可以把AbstractFactory转型为某个具体类型工厂传递给特定的生成模块。

譬如T类型的文件只关心生成T,所以你可以传递AbstractFactory<T>,该文件所要做的只是实现T的DoCreate方法。

到此我们对这个框架有了大致的理解,但是还是没有说明如何实现DoCreate,其实解决方法比想像中的要简单。

template    <class ConcreteProduct,class Base>
class    OpNewFactoryUnit    :public    Base
{
    typedef    typename    Base::ProductList    BaseProductList;
protected:
    typedef    typename    BaseProductList::Tail    ProductList;
public:
    typedef    typename    BaseProductList::Head    AbstractProduct;
    ConcreteProduct
*    DoCreate(Type2Type<AbstractProduct>)
    
{
        
return    new    ConcreteProduct;
    }

}
;

如此所有产品都得到了DoCreate方法。但是有个问题,OpNewFactoryUnit的包含文件要知道所有的产品类。其实这不是问题,我们来看ConcretteFactory的实现再讨论这个问题:

template    <class AbstractFact,
            template 
<class,class,> class Creator = OpNewFactoryUnit
            
class TList = typename AbstractFact::ProductList
            
>
class ConcreteFactory
    :
public    GenLinearHierarchy<typename TL::Reverse<TList>::Result,Creator,AbstractFact>
{
public:
    typedef    typename    AbstractFact::ProductList    ProductList;
    typedef    TList        ConcreteProductList;
}
;

首先一个问题,OpNewFactoryUnit在定义的时候不需要知道任何类,因为它只是操作模板参数,而它的使用地方是在ConcreteFactory中,这个时候一个参数就是TList,TList肯定知道需要的一切类,这个需要的代价就是文件包含。当然,OpNewFactoryUnit没有任何多于文件依赖。

上面代码也展示了具体工厂的实现。ConcreteFactory(最终)继承于AbstractFactory,所以获取产品的方法不会有任何修改。所以这里无需定义太多东西。而ConcreteFactory最后的继承于一个施加于OpNewFactoryUnit的TList作用的AbstractFactory。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:181614次
    • 积分:2942
    • 等级:
    • 排名:第12784名
    • 原创:113篇
    • 转载:3篇
    • 译文:0篇
    • 评论:28条
    文章分类