由AF再论template

template的伟大魅力在于它的自动生成代码能力,基于template的技术,无论多么高深仰或多么花哨,只要你明白它的自动生成代码的本质,问题会好处理很多。

譬如AbstractFactory在template下的loki做法,它只是为了让编译器帮我们生成代码而已,如果你考虑手写代码,问题会好理解很多。

A抽象基类问题

如果你要使用AbstractFactory模式,那你首先要有一个基类,它定义了生成方法。Loki定义了如此一个接口:

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

这是一个模板化的东西,明显,在不同的类参与作用下,这会被实例化出一系列类,这是与AF有悖的,毕竟AF我们希望使用统一一个基类,为了支持到这一点,Loki使用了强大的外星动力:GenScatterHierarchy。如此我们得到了一个统一的唯一的接口:

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>());
    }

}
;

尽管这个AbstractFactory是一个多类的组合体,只是它可以作为一个类使用处理,但这不仅仅保证了一个唯一的基类,还给我们提供了额外的优势——细粒度化,你可以对不同的模块传递它的不同颗粒,本模块不必知晓任何一点与自己无关的颗粒以及与该颗粒管理的类、包含关系。

我们回顾AF模式,它要求基类只需要提供统一接口。ok,这个AbstractFactory已经满足这个要求了。使用AF的时候抽象基类问题到此得到完美解决。

B子类实现问题

AF有几个要求,子类要继承基类,并且实现基类的方法,子类也应该是一个唯一的类。

基类已经是一个多颗粒的东西,子类必然是多颗粒的,单又要都继承于AbstractorFactory而且又要保证自己的外观是单颗粒的,只有逐一继承最后包装,GenLinearHierarchy可以帮上这个忙,它可以产出都继承于某一类的类(如果你习惯使用loki的时候使用默认参数,我建议你要多全部参数的声明有个了解),而且它可以对TList操作,不要忘记,AbstractFactory也使用了TList,使用同样的TList可以使你得到完美的继承体系。

满足了继承关系,还要重写基类的虚函数,使用policy是个不错的选择,为继承体系中的每个类都加入一个实现了虚函数的policy,这样每个类都有了虚函数的实现,而每个类又恰恰继承于基类,这简直太完美了,巧合还是人为?难以一言蔽之。

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;
}
;

使用TL和Creator创建继承于AbstractFact的线性类表,而ConcreteFactory继承于这个线性表,或者可以说ConcreteFactory是对多颗粒的一个单粒度封装。还是太完美了。

到这里实现Creator规则太简单了。

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;
    }

}
;

Creator没有什么特别的,按照指定规则做事而已。

到这里AF已经被Loki包装成完全自动生成代码的东西了,你只需提供少量的信息,就可以批量获取产品,这才是工厂。

    typedef    AbstractFactory < LOKI_TYPELIST_3(Base,Test1,Test2) >     MyKit;
    
// MyKit*    pKit    = new    MyKit;
    
// Test2*    t2    = pKit->Create<Test2>();

    typedef    ConcreteFactory
< MyKit >     MyConKit;

    MyConKit
*     pKit     =   new     MyConKit;
    SmartPtr
< Test2 >     t2     =  pKit -> Create < Test2 > ();
    t2
-> say();
    SmartPtr
< Test1 >     t3     =  pKit -> Create < Test1 > ();
    t3
-> say();

不管如何美化,template还是为了生成代码,这是它的本质,用这个本质考虑template参与情况下的问题会容易理解很多。分析使用AF的时候的逐个细节并归纳,你也可以完成这些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值