6. 提取并重写调用
和第四条类似, 只不过封装的是变量的访问.
原始代码:
1
Class TargetCls
2

{
3
private InnerObjCls innerObj = new InnerObjCls();
4
5
public void TargetFun()
6
{
7

8
innerObj.Fun();
9

10
}
11
}
重构:

Code
1
Class TargetCls
2

{
3
private InnerObjCls innerObj = new InnerObjCls();
4
5
public void TargetFun()
6
{
7

8
InnerObjFun();
9

10
}
11
12
protected virtual void InnerObjFun()
13
{
14
innerObj.Fun();
15
}
16
}
17
18
Class TestCls : TargetCls
19

{
20
protected override void InnerObjFun()
21
{
22

23
}
24
}
我们把测试方法内部依赖的对象叫'问题对象'. 如果问题对象上只有唯一一个方法的话, 提取并重写调用比较容易, 但如果同一对象上有多个问题方法的话, 我们可能就需要下面的手法了--提取并重写获取方法.
7. 提取并重写获取方法
原始代码:

Code
1
Class TargetCls
2

{
3
private InnerObjCls innerObj = new InnerObjCls();
4
5
public void TargetFunOne()
6
{
7
innerObj.FunOne();
8
}
9
10
public void TargetFunN()
11
{
12
innerObj.FunN();
13
}
14
}
重构:

Code
1
interface IInnerObject
2

{
3
void FunOne();
4
void FunN();
5
}
6
7
class InnerObjCls : IInnerObject
8

{
9
public void FunOne()
{}
10
public void FunN()
{}
11
}
12
13
class FakeInnerObj : IInnerObject
14

{
15
public void FunOne()
{}
16
public void FunN()
{}
17
}
18
19
Class TargetCls
20

{
21
private InnerObjCls innerObj = null;
22
23
protected virtual IInnerObject getInnerObj()
24
{
25
if(innerObj == null)
26
{
27
innerObj = new InnerObjCls();
28
}
29
return innerObj;
30
}
31
32
public void TargetFunOne()
33
{
34
getInnerObj().FunOne();
35
}
36
37
public void TargetFunN()
38
{
39
getInnerObj().FunN();
40
}
41
}
42
43
Class TestCls : TargetCls
44

{
45
protected override IInnerObject getInnerObj()
46
{
47
return new FakeInnerObj();
48
}
49
}
类似抽象工厂, 可以把每一个问题方法看做一个产品类, 获取方法返回的是一个具体的工厂. 这种方法从工厂这个接缝解开了大量具体的产品接缝.
8. 定义Set方法; 特征提取, 创建方法对象.
PⅢ, 联系
比较重要的是子类化重写和接口提取. 通常, 应用子类化重写解除测试方法内部调用本类方法的依赖; 应用接口提取解除测试方法内部调用变量对象(其他类型)方法的依赖.
PⅣ, 语录
PⅤ, 备注
本文只记录了适用于面向对象方式的解依赖技术, 不做其他方面(过程, 函数)的介绍.