一、Move Method(搬移函数)
在A类中有一个A函数与B类中进行更多交流或者被B类调用,可以将A函数变为委托函数,然后移除A函数。
做法:
1、检查源类中字段与函数,考虑是否被搬移。
2、检查源类的子类和父类,看看是否有该函数的其他声明。
3、在目标类中声明这个函数。
4、将源函数的代码复制到目标函数中。
5、编译目标类。
6、决定如何从源函数正确引用目标对象。
7、修改源函数,将当作委托函数。
8、将源类中的源函数替换为目标函数。
9、编译、测试。
范例:
class Account
{
private AccountType _type;
private int _daysOverdrawn;
public double OverdraftCharge()
{
if (_type.IsPremium())
{
double result = 10;
if (_daysOverdrawn > 7)
result += (_daysOverdrawn - 7) * 0.85;
return result;
}
else
return _daysOverdrawn * 1.75;
}
public double BankCharge()
{
double result = 4.5;
if (_daysOverdrawn > 0)
result += OverdraftCharge();
return result;
}
}
将OverdraftCharge()复制到AccountType类中.
class AccountType
{
public bool IsPremium()
{
return true;
}
<span style="color:#ff0000;"> public double OverdraftCharge(int daysOverdrawn)
{
if (IsPremium())
{
double result = 10;
if (daysOverdrawn > 7)
result += (daysOverdrawn - 7) * 0.85;
return result;
}
else
return daysOverdrawn * 1.75;
}
</span> }
替换Account类中的OverdraftCharge(),并将其删除。
class Account
{
private AccountType _type;
private int _daysOverdrawn;
public double BankCharge()
{
double result = 4.5;
if (_daysOverdrawn > 0)
result += <span style="color:#ff0000;">_type.OverdraftCharge(_daysOverdrawn);
</span> return result;
}
}
二、Move Field(搬移字段)
类A中某个字段被B类的更多的用到,把该字段搬移到B类中。
做法:
1、如果字段是public,使用Encapsulate Field将它封装。
2、编译、测试。
3、在目标类中建立与源类中相同的字段,并使用属性get/set。
4、编译目标类。
5、如何在源类中引用目标类。
6、删除源字段。
7、将引用的源字段替换成目标字段。
8、编译、测试。
三、Extract Class(提炼类)
某个类做了应该由两个类做的事,建立新类,将相关字段和函数从旧类中搬移到新类。
做法:
1、决定类的责任。
2、建立新类,把责任从旧类中分离出来。
3、从旧类访问新类的连接关系。
4、对于字段,运用Move Field搬移。
5、编译、测试。
6、使用Move Method先搬移低层函数,然后高层函数。
7、编译、测试。
8、检查,精简每个类的接口。
9、决定是否公开新类。
class Person
{
private string _name;
private string _officeAreaCode;
private string _officeNumber;
public string Name
{
get { return _name; }
}
public string OfficeAreaCode
{
get { return _officeAreaCode; }
set { _officeAreaCode = value; }
}
public string OfficeNumber
{
get { return _officeNumber; }
set { _officeNumber = value; }
}
public string GetTelephoneNumber()
{
return "(" + _officeAreaCode + ")" + _officeNumber;
}
}
添加一个新类。并把字段与函数搬移到新类中。
class TelephoneNumber
{
private string _officeAreaCode;
private string _officeNumber;
public string OfficeAreaCode
{
get { return _officeAreaCode; }
set { _officeAreaCode = value; }
}
public string OfficeNumber
{
get { return _officeNumber; }
set { _officeNumber = value; }
}
}
修改旧类。
class Person
{
private string _name;
private TelephoneNumber _telephoneNumber = new TelephoneNumber();
public string Name
{
get { return _name; }
}
public string GetTelephoneNumber()
{
return "(" + _telephoneNumber.OfficeAreaCode + ")" + _telephoneNumber.OfficeNumber;
}
}
四、Inline Class(将类内联化)
某个类没有做太多事情,将这个类的所有特性搬移到另一个类中,然后移除原类。
1、在目标类身上声明源类的public协议,并将其中所有函数委托至源类。
2、修改所有源类引用点,改而引用目标类。
3、编译、测试。
4、运用Move Method和Move Field,将源类的特性全部搬移到目标类。
五、Hide Delegate(隐藏委托)
客户通过一个委托类来调用另一个对象。在服务类上建立客户所需的所有函数,用以隐藏委托关系。
1、对于每一个委托关系中的函数,在服务对象端建立一个简单的委托函数。
2、调整客户,令它只调用服务对象提供的函数。
3、每次调整后,编译并测试。
4、如果将来不再有任何客户需要取用图7-1的Delegate(受托类),便可移除服务对象中的相关访问函数。
5、编译、测试。
class Department
{
private string _chargeCode;
private Person _manager;
public Department(Person manager)
{
_manager = manager;
}
public Person Person
{
get { return _manager; }
}
}
class Person
{
Department _department;
public Department Department
{
get { return _department; }
set { _department = value; }
}
<span style="color:#ff0000;"> public Person GetManager()
{
return _department.Person;
} </span>
}
如果客户希望知道某人的经理是谁,他必须先取得Department对象。即: Person p = new Person(); Department d = new Department(p);
这样的编码就是对客户揭露了Department的工作原理,隐藏Department,可以减少耦合。在Person中建立一个简单的委托函数。
六、Remove Middle Man(移除中间人)
某个类做了过多的简单委托动作,让客户直接调用受托类。
1、建立一个函数,用以获得受托对象。
2、对于每个委托函数,在服务类中删除该函数,并让需要调用该函数的客户转为调用受托对象。
3、处理每个委托函数后,编译、测试。
七、Introduce Foreign Method(引用外加函数)
你需要为提供服务的类增加一个函数,但你无法修改这个类。
在客户类中建立一个函数,并以第一参数形式传入一个服务类实例。
1、在客户类中建立一个函数,用来提供你需要的功能。
2、以服务类实例作为函数的第一个参数。
3、将该函数注释为:“外加函数(Foreign Method),应在服务类实现”。
DateTime newStart = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day + 1);
变为一个外加函数:
private static DateTime NextDay()
{
return new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day + 1);
}
八、Introduce Local Extension(引入本地扩展)
你需要为提供服务的类增加一个函数,但你无法修改这个类。
建立一个新类,使它包含这些额外函数。让这个扩展品成为源类的子类或包装类。
1、建立一个扩展类,将它作为原始类的子类或包装类。
2、在扩展类中加入转型构造函数。
3、在扩展类加入新特性。
4、根据需要,将源对象替换为扩展对象。
5、将针对原始类定义的所有外加函数搬移到扩展类中。