Modern C++ Design 笔记 第九章 Abstract Factory

再没有读这章的时候就在想,上一章是factory那这章是不是就是Abstract Factory了。果不其然啊!
一样的,在开始描述之前,援引wikipedia的定义来看看:
A software design pattern, the Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme. In normal usage, the client software would create a concrete implementation of the abstract factory and then use the generic interfaces to create the concrete objects that are part of the theme. The client does not know (or care) about which concrete objects it gets from each of these internal factories since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from its general usage.
这个非常学术的定义简单点的描述就是,Abstract Factory是具体工厂类的抽象,可以创建出多个抽象工厂的具体派生工厂。应用程序无须知道当前使用的是什么派生类,依然可以创建一组工厂的产品。很多的情况下,很多教材愿意给出一个UIFactory的例子, 比如说像下面这个:(本着无图无真相的原则,王道是一定要上的)

可以看到Application拿着GUIFactory的句柄(引用,指针?随便)而不关注具体的是什么派生类Win或者OSX,每次只要createButton就可以拿到一个button的引用而不知道什么具体的什么工厂的Button。显然这样让应用程序可以和具体的UI解耦,从而可以轻松替换UI风格。

大致说了什么是Abstract Factory之后,我们进入有点枯燥的实现。这里的实现还是相当的抽象。

首先,第一步。就像前面描述的一样,我们至少需要一个AbstractFactory的基类,用以后面具体的类型来做派生。值得注意的一点是,这里的继承关系比较复杂,还不是象上面图中的直接继承。下面是AbstractFactory类的大致实现

(现在的代码编辑器好差啊!)

注意,我们这里用到了GenScatterHierarchy这个模板。(这个模板不明白的话只好看看第三章了)这个模板可以帮助我们生成了一堆分散的类。书中给出了这样一个例子

typedef Loki::AbstractFactory<LOKI_TYPELIST_3(Soldier, Monster, SuperMonster)> AbstractEnemyFactory;

这样一个语句却为我们生成了一个分散的类层次结构。

 

分散的类 (图一)

现在看这个类,我们至少知道了一些信息,比如AbstractEnemyFactory从AbstractFactoryUnit<Soldier>这样的一组类继承下来。但是又有很多不明白的,如AbstractFactoryUnit怎么工作呢?或者要怎么来实现一个AbstractFactoryUnit的派生类,然后又如何让这个ConcreteFactoryUnit和ConcreteFactory合作呢?带着很多的疑问,我们进入了下一个ConcreteFactory的实现就豁然开朗了(其实没有这么快的,这个一个很艰难的过程)。

这里有个ConcreteFactory的实现,这里用到了GenScatterHierarchy的兄弟GenLinearHierarchy。

初看这个代码的时候更糊涂了,为什么OpNewFactoryUnit和之前的Unit好像没有什么关联?这样怎么创建对象呢?还有这个ConcreteFactory为什么不直接从AbstractFactory来,要搞这么多奇怪的GenLinearHierarchy的使用呢?我们还是先来看看这个具体的语句声明以后产生的类图吧

typedef Loki::ConcreteFactory<AbstractEnemyFactory, Loki::OpNewFactoryUnit,
  LOKI_TYPELIST_3(SillySoldier, SillyMonster, SillySuperMonster)> EasyLevelEnemyFactory;

(图二)

 

尽管这个图片比较小,但是我们依然能够清楚的把握到2点:

1. EasyLevelEnemyFactory还是从AbstractEnemyFactory继承下来的,只是中间经历了很多过程。所以我们还是可以像普通的抽象工厂一样的工作。

2. 这个抽象层次中产生的类例如OpNewFactoryUnit<SillySoldier, AbstractEnemyFactory>继承与AbstractFactory,也就是说他们继承于AbstractFactoryUnit<Soldier>。(请参照图一)

 

所以看到现在我们再回过头来看AbstractFactory中的Create()函数的时候就不足为奇了:

假设我们有如下这样的调用:

    std::auto_ptr<AbstractEnemyFactory> easyFactory(new EasyLevelEnemyFactory);
    Soldier *s;
    s = easyFactory->Create<Soldier>();

通过分析可以知道,easyFactory这个AbstractEnemyFactory的智能指针指向了一个EasyLevelEnemyFactory的实例,在Create<Soldier>()函数调用的时候发生了什么呢?首先调用了AbstractFactory的Create函数(因为ConcreteFactory根本没有这个接口)

后面的事情就是DoCreate的实现啦。书中给出了一个传统的实现就是每次都New一个,还有一个实现就是所谓的prototype模式的应用,这就不是AbstractFactory讨论的重点了。

 

这里来总结一下,可以看出这个模型的设计着有鬼神之才。如此繁复的模型看着都觉得麻烦,那设计出来的人岂不是。。。

不管了, 关键的问题是要理解。所以简单点的说就是AbstractFactory和ConcreteFactory套用GenScatterHierarchy和GenLinearHierarchy产生了一个巨大的层次结构,完成了抽象工厂模型的建立。理解起来很麻烦,但是用起来,确实很爽。而且那些具体的Unit还和Factory没有复杂的耦合,确实是吐血推荐了:)

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值