手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>C/C++>列表

乌托邦式的接口和实现分离技术

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

  请注意,一个接口能够有任意多个实现,并且能够是任意的部分实现。<!--[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
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!