第六章(隔离)

都在说解耦合,但是如何解,哪些情况下有偶尔呢?看看前人的总结总是好的

此处都是针对编译时的解偶尔,不涉及链接和最后发布。

1、编译时耦合

1.1 IsA的关系

继承:class D: public B

不管继承方式,B的变化都将影响D的重新编译。D的重新编译将会继续递归下去

1.2 Has A/holds A

D中包含b1,b2对象。b1,b2的变化会影响D的编译

1.3 内联函数

D内联函数的实现变化,都会影响包含接口的重新编译。内联函数尽量不要有函数调用,这样其实是有依赖关系下去的。

1.4私有成员/保护成员

与1.2有点类似,private变量的类型,增加,删除都会影响该类。函数参数,返回值也会影响其重新编译

1.5 包含指令

明确的include。不用include的头文件被包含,也会导致相应文件重新编译

1.6 默认参数

默认参数变化

1.7 枚举类型变化

宏定义,typedef,const全局值,枚举都会导致重新编译

所以所有错误码或则类型定义在一个头文件中,对于大型项目不是什么好方法


2、隔离技术。如何隔离,针对相应情况相应的处理,而不是完完全全按照下面方法,因为这些方法也有弊端

2.1 移除私有继承

因为是私有继承,目的一般是希望使用里面的部分方法作为辅助。

解决方案:通过代理模式即可,将继承的基类申明成成员类。然后子类提供部分访问函数,另外此处不要使用内联,否则就还是进入了耦合。失去了代理,前置申明解耦的意义了。另外写代码时候发现一个私有继承比较有意思的写法

基类

class CInsulateHelp
{
public:
 CInsulateHelp();
 ~CInsulateHelp();

 void f(int);
protected:
 void f_protected(int);
private:
 
};

子类私有继承

class CInsulate: private CInsulateHelp
{
public:
 CInsulate();
 ~CInsulate();
 
 void Test();

 // 该语句注释掉,f就是protected了,是无法被外部访问的了。
 // 因为是private继承。函数也是成员对象!!!,也可以当变量使用
 CInsulateHelp::f;

 // 也可以把protected的成员申明成public.但是无法改变private类型,因为private子类自己都访问不到。
 CInsulateHelp::f_protected;
private:
};

解耦的重写方法就是在CInsulate申明一个CInsulateHelp的指针即可。当然指针在内部就需要注意operator=,拷贝,析构指针的用法了。可以使用scoped_ptr,shared_ptr来明确所有权

2.2 消除嵌入式数据成员

与2.1改写方式类似,使用代理模式即可,将成员变量有对象改写为指针

2.3 消除私有成员函数

因为私有成员函数变量也会导致类变化,如果私有成员函数的功能是辅助函数,我们完全可以通过其它方式解耦合。

通过提供静态函数或则全局函数,当然实现是在cpp中,如果需要使用类中的变量,第一个参数用this指针即可解决。

static void fHelp(CInsulateHelp* pHelp, int)
 {

 }

2.4 移除保护成员函数

如果基类提供一些保护成员函数,目的是给子类使用,方便子类在实现virtual时调用。这样实际会污染基类,让基类去关心子类,提供帮助给子类了

class Base

{

public:

virtual void draw() = 0;

protected:

void drawLine(); // 方便子类画圆

}

改进方案

提供一个专门的辅助类,需要使用包含它,不需要的不用它,减少了基类的负担和耦合,如果需要基类成员变量,提供一个this指针即可

class Scribe

{

pulbic;
void drawLine();

}

2.5 同样是2.4的问题,另外的一种解决方法

如果2.4中单独提取一个辅助类不合适,比如2.4中需要使用this指针去改变成员的值,即子类需要访问的不仅仅是辅助函数,而是实际需要设置基类成员的函数,需要与基类紧密相连的,拆离到单独的类中会将类的职责搞混乱。不太合适分离

我们可以为Base提供一个供客户使用的纯虚接口类,只提供draw

再提供一个BaseImpl继承自Base,提供一些真正要设置成员的函数,真正的实现再继承自BaseImpl。这样BaseImpl的变化,不会影响客户的编译,而子类又使用了各个辅助函数,或则设置函数。


2.6 移除编译器生成的函数

2.7 移除包含指令

2.8 删除默认参数

2.9 删除枚举类型

      1.私有枚举类型可以放到cpp中

       2.枚举常量可以通过static const int代替,然后提供static的访问函数,这样值变化,不会导致其它文件重新编译。但是可能会影响性能,因为多一个间接访问函数

       3.枚举用作返回值,参数类型,尽量定义在类的内部,不要试图去重用它们,不用把它们和其它类似的放在一块。如该文件的错误码就放在该文件中,不用把所有错误码放在一个文件中


3. 整体的隔离技术

3.1 协议类。即抽象接口类,是一个近乎完美的隔离器

不包含任何成员变量,不继承任何类

有一个virtual的析构函数

其它成员,全都是纯虚的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值