分类: C/C++
2013-03-01 11:48:28
在平常工作中,用过很多设计模式,但是今天我要描述的应该是被我用的最多的,因为它的抽象功能很强大,在很多场合都可以被用上。有趣的是,这种设计模式又有很多种变形,这些变形可以用于不同的平衡策略。下面我们来一一讲解它们。
1. Problem(问题)
如果我们想要给某个类加上计数功能,这个功能可以使我们很轻易的知道,这个类当前有多少实例。我想很多人都会知道怎么做:
与设计类库一样,我们做这种基础设施的设计,其接口设计必须满足如下规范:
a. 易于使用 : 我们的接口必须设计成易于使用,我们内部的复杂度,客户是不关心的。所以我们要把复杂度隐藏起来(对客户)。为什么要这样?这样我们的客户才愿意使用你设计的类库或者基础设施。否则别人肯定会另起炉灶,而拒绝使用你提供的东西。或者在你提供的东西上包装一层。这都不是我们想要的,如果他能包装,我们为什么不提供包装好的东西?
b. 效率: 我们必须考虑空间和时间上的成本。尽量不增加不必要的额外成本。(但这不是最重要的,第一条才是我们最需要优先考虑的)
另外一个需求是,我们必须找到一种语言特性,能够为客户类自动生成一个静态变量,并在构造是自增,析构时自减。下面我们将会看到,有哪些方法可以做到这点。
3. implementation (实现)
1) Solution-1 (方案一)公共继承
继承是很多人,特别是c++初学者最喜欢用的复用方法(我也喜欢用 :)),所以这里把它排在第一位。
如果使用继承,那就意味着我们有一个基类,被不同的类继承时,能为自动生成一个静态变量。什么语言特性可以做到这点?template。对,就是它。下面我们来看看如何实现:
只要我们为这个类指定一个不同的模板参数,它就会为我们生成一个新的类,这个新类的所有成员都是独立的。
下面让我们来看看,我们是如何使用它的:
就这么简单,只要一个继承就可以了。你如果向你的同事推销这个功能类,我觉得没人有理由拒绝它。如果有一千个类需要这个功能,你这么简单的一个基类,为大家减少的工作量,可想而知。
什么?你问我这个为什么能工作,好吧。我建议你去学习一下C++模板。你也许很奇怪,为什么我的myClass可以继承于一个以我自己为模板参数的基类。呵呵,它就是可以,而且你也看到了,其实这个模板参数并没有什么作用,只是告诉编译器,为我生成一个特别的独立的类,并拷贝这个模板中的所有成员。
好的,到这里,我想很多人会激动,因为他们学了一个新招,跃跃欲试。但是到了现实世界中,我们会碰到很多困扰,比如说如下情况:
如果你把那个counter类用在这个myClass中的时候,肯定会有人质疑你,说:no,我们不可以用多重继承,它会为我们引起麻烦。你会怎么回答?有没有立即感到沮丧?
别,现实和理想是有差距,但是差距并不像我们想象的那么大。你告诉他:我们的基类里面没有任何数据成员,你可以安全的用它,它不会为你带来麻烦的。
如果你的资历比较浅,而别人又用头衔压你,说你不能这么做,不能用多重继承。好吧,那么我们可以考虑如下方法:
看,我们也可以用内嵌的方式同使用这个模板类。但是我们需要多写一些代码。如果我们还是想用一行代码解决问题,应该怎么做呢?
下回分解。