请注意,一个接口能够有任意多个实现,并且能够是任意的部分实现。<!--[if !supportEmptyParas]--> <!--[endif]-->
假设我们有如下接口继承树:
| InterfaceN àInterfaceN_1àInterfaceN_2à…àInterface0 |
并且提供了实现类ImpInterface0 ~ ImpInterfaceN.
那么,InterfaceN的实例类型就是:
| typedef ImpInterfaceN< ImpInterfaceN_1< ImpInterfaceN_2< … ImpInterface0<InterfaceN> …> > > ConcreteClassN; |
我们注意到,定义ConcreteClassN的时候,我们的ImpInterface是按照顺序来的,我认为这是合适的做法。当然了,最后组装的权力已交给客户了,客户爱怎么组装就怎么组装吧。然而我们还是有一些需要注意的问题。
1.假定,我需要在ImpInterfaceI中引用基类的方法,记住,不要使用这样的手法:
| ImpInterfaceI_K::SomeMethod(); |
这样调用不具备多态性,而应该这样:
| this-> SomeMethod(); |
2.不要在自己的ImpInterfaceI实现中覆盖基类接口的其他已实现的方法,假如您一定要这么做,那么务必在文档中说明,因为在组装的时候,顺序将是极其关键的了。
3.这个方法和设计模式中的Template Pattern目的是不相同的。Template Pattern是在基类中定义了一个算法,让派生类定制算法的某些步骤。这里的方法针对的是接口模型的概念,提供接口和实现分离的技术。
关于第二条,应该尽量避免发生。这里说的覆盖是指基类实现已实现了该方法,而后继实现又覆盖该方法。基类实现能够是个部分实现,对于没有实现的那些方法,在派生接口的实现类中实现则是常见的。一方面,我们尽量合理分解层次之间的功能,另一个方面,能够通过定制实现模板类,来确保顺序。尽可能的让语言本身来确保正确性,而不是依赖文档。我们能够像这样预先装配一些东西:
| template<typename Base> class SomeComponent : public ImpPartA < ImpPartB <Base> >{}; |
可惜,C 暂时还不支持模板的不完全typedef,否则,我们还能够如下定以:
| template<typename Base> typedef ImpPartA< ImpPartB<Base> > SomeComponent; |
但是,C0x很可能会支持类似的语法。这样,我们使用SomeComponent来作为一个预制品,来确保一些安全性,而不必完全依赖文档了。 <!--[endif]-->
看看ConcreteClassN的定义,也许您和我相同,并不喜欢这种嵌套的、递归的定义方式,太难看了。让世界稍微美好一点吧!于是我们提供一个辅助类:
| <!--[if !supportEmptyParas]--> template<typename T>struct Empty{}; template<typename I, typename template<class> class B> struct Merge{ <!--[if !supportEmptyParas]-->typedef B<I> type;}; template<typename I > struct Merge<I, Empty >{ typedef I type; <!--[if !supportEmptyParas]--> }; <!--[endif]--> template < typename I, typename template<class> class B1, typename template<class> class B2 = Empty, … typename template<class> class Bn = Empty, > struct Reform{ typedef typename Merge< typename Merge< typename Merge<I, B1>::type , B2>::type , …,Bn>::type type; }; |
现在,我们能够这样定义ConcreteClassN了:
| Typedef Reform<InterfaceN, ImpInterface0, ImpInterface1, …ImpInterfaceN>::type ConcreteClassN; |
是不是清爽了很多?
在继续下面内容以前,请回味一下这个不是问题的问题:
假设IReader有3种实现,IRefCount有3种实现,我们将如何漂亮地解决掉他们。 <!--[endif]-->
现实世界总是要复杂得多,让我们进入真实的世界。回顾这个接口:
| struct IRWiter : IReader, IWriter; |
假设我们确实需要IReader, IWriter,但是并无需IRWrite,可不能够让一个对象同时支持这两个接口呢,就像COM相同?当然能够,我们借助于这样一个辅助模版:
| template<typename B1, typename B2> struct Combine : B1, B2{ typedef B1 type1; typedef B1 type2; <!--[if !supportEmptyParas]--> }; <!--[endif]--> typedef Reform< Combine<IReader, IWriter>, ImpRefCount, ImpWriter, ImpReader >::type ConcreteRWiter |
为了现实需要,我们能够提供Combine的多个特化版本以支持任意数量的接口组合。假如仅仅是为了去掉一个IRWiter就引入一个Combine,虽有好处,但是意义也不大。那么,考虑这样一个例子。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




