《重构--改善既有代码的设计》--处理概括关系(11)
2015-07-30 17:12
681 查看
一、Pull Up Field(字段上移)
两个子类拥有相同的字段。将该字段移至超类。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/064e86d99d7cac34c6e070f3b0268c31)
二、Pull Up Method(函数上移)
有些函数,在各个子类中产生完全相同的结果。将该函数移至父类。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/8da40e3ddc917b2f20b5d0052bd88658)
1、检查待提升函数,确定它们是完全一致的。
2、如果特提升函数名不同,修改与父类相同的函数名。
3、在父类新建一个函数,将待提升的函数代码复制到到新函数中。
4、编译。
5、移除子类中的函数。
6、编译、测试。
7、逐一移除子类中的函数,直到只剩下父类中的函数。
8、编译、测试。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/631fbf5d37a18139de774462607ca898)
重构后:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/fae41555a67c61687c9778400420cfc4)
三、Pull Up Constructor Body(构造函数本体上移)
你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。在父类中新建一个构造函数,并在子类构造函数中调用它。
1、在父类定义一个构造函数。
2、将子类共同代码搬移到父类中构造函数中。
3、将子类构造函数共同代码删除,改用父类中的构造函数。
4、编译、测试。
重构后:
四、Push Down Method(函数下移)
父类中的某个函数只与部分(而非全部)子类有关。将这个函数移到相关的那些子类去。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/2d16f8825c05413f34eaa2c59eb70299)
五、Push Down Field(字段下移)
父类中某个字段只被部分(而非全部)子类用到。将这个字段移到需要它的那些子类中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/e090772ea878eb2947b024273885ce94)
六、Extract Subclass(提炼子类)
类中的某些特性只被某些(而非全部)实例用到。新建一个子类,将上面所说的那一部分特性移到子类中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/b3f4ececdc7a831378827993a88dae06)
1、为源类定义一个新的子类。
2、为这个新的子类提供构造函数。
3、找出父类的构造函数,如果是需要子类的构造函数,请替换之。
4、逐一使用Push Down Method和Push Down Field将源类的特性移到子类。
5、编译、测试。
创建一个子类,重构后:
客户端:
七、Extract Superclass(提炼超类)
两个类有相似特性。为这两个类建立一个父类,将相同特性移至父类。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/5dbc5d4444bd64a69b1d1b53099afa9a)
1、建立一个抽象父类。
2、运用Pull Up Field,Pull Up Method,Pull Up Constructor Boday逐一将子类共同元素上移到父类。
3、编译、测试。
八、Extract Interface(提炼接口)
若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/dfd061e8bbfeac5a9ded8cea49f431a0)
1、新建一个接口。
2、在接口中声明待提炼类的共通操作。
3、让相关的类实现其接口。
4、调整客户端的类型声明,令其使用该接口。
重构后:
九、Collapse Hierarchy(折叠继承体系)
父类与子类之间无太大区别,将它们合为一体。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/49a3e70e3081e1f3e280faed2d65f8cb)
1、选择你想移除的类:父类或子类。
2、使用Pull Up Field,Pull Up Method或Push Dwon Field,Push Down Method,把想移除的行为和属性搬移到另一个类中。
3、编译、测试。
4、调整原类的引用点,改为新类的引用。
5、移除源空类。
6、编译、测试。
十、Form Template Method(塑造模板函数)
你有一些子类,其中相应的函数以相同的顺序执行类的操作,但各个操作的细节上有所不同。将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同了。然后将原函数上移至父类。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/03ff288798db798c2034865f6934beda)
1、在各个子类中分解目标函数,使分解后的各个函数不完全相同。
2、运用Pull Up Method将各个子类完全相同的函数上移父类。
3、对于那些完全不同的函数,实施Rename Method,使这些函数的签名完全相同。
4、编译、测试。
5、运用Pull Up Method将所有函数逐一上移到父类,并声明为抽象函数。
6、编译、测试。
7、移除子类中的原函数,编译、测试。
重构后:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/4fdccd593e4da0d536d1d90a29f0af36)
十一、Replace Inheritance with Delegation(以委托取代继承)
某个子类只使用父类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存父类,调整子类函数,令它改而委托父类,然后去掉两者之间的继承关系。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/d3643b9619a724dcf03ab46c1975a9d2)
1、在子类型新建一个字段,引用父类的一个实例。
2、修改子类所有函数,让它们不使用父类,转而使用字段。
3、编译、测试。
4、去除继承关系。
5、编译、测试。
十二、Replace Delegation with Inheritance(以继承取代委托)
你在两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数。让委托类继承受托类。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/14/8b8c79488588ab469d0ccf91ae64a81c)
1、让委托端成为受托端的子类。
2、编译。
3、将受托字段设为该字段所处对象本身。
4、去掉简单的委托函数。
5、编译、测试。
6、把调用委托的代码改为对象本身。
7、移除受托字段。
重构后:
两个子类拥有相同的字段。将该字段移至超类。
二、Pull Up Method(函数上移)
有些函数,在各个子类中产生完全相同的结果。将该函数移至父类。
1、检查待提升函数,确定它们是完全一致的。
2、如果特提升函数名不同,修改与父类相同的函数名。
3、在父类新建一个函数,将待提升的函数代码复制到到新函数中。
4、编译。
5、移除子类中的函数。
6、编译、测试。
7、逐一移除子类中的函数,直到只剩下父类中的函数。
8、编译、测试。
重构后:
三、Pull Up Constructor Body(构造函数本体上移)
你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。在父类中新建一个构造函数,并在子类构造函数中调用它。
1、在父类定义一个构造函数。
2、将子类共同代码搬移到父类中构造函数中。
3、将子类构造函数共同代码删除,改用父类中的构造函数。
4、编译、测试。
class Employee { protected string _name; protected string _id; public Employee(string name, string id) { _name = name; _id = id; } }
class Manager : Employee { private int _grade; public Manager(string name, string id, int grade) { _name = name; _id = id; _grade = grade; } }
重构后:
class Manager : Employee { private int _grade; public Manager(string name, string id, int grade) :base(name,id) { _grade = grade; } }
四、Push Down Method(函数下移)
父类中的某个函数只与部分(而非全部)子类有关。将这个函数移到相关的那些子类去。
五、Push Down Field(字段下移)
父类中某个字段只被部分(而非全部)子类用到。将这个字段移到需要它的那些子类中。
六、Extract Subclass(提炼子类)
类中的某些特性只被某些(而非全部)实例用到。新建一个子类,将上面所说的那一部分特性移到子类中。
1、为源类定义一个新的子类。
2、为这个新的子类提供构造函数。
3、找出父类的构造函数,如果是需要子类的构造函数,请替换之。
4、逐一使用Push Down Method和Push Down Field将源类的特性移到子类。
5、编译、测试。
class JobItem { private int _unitPrice; private int _quantity; private bool _isLabor; private Employee _employee; public JobItem(int unitPrice, int quantity, bool isLabor, Employee employee) { _unitPrice = unitPrice; _quantity = quantity; _isLabor = isLabor; _employee = employee; } public int GetTotalPrice() { return GetUnitPrice() * _quantity; } public int GetUnitPrice() { return (_isLabor) ? _employee.GetRate() : _unitPrice; } public int Quantity { get { return _quantity; } } public Employee Employee { get { return _employee; } } }
class Employee { protected int _rate; public Employee(int rate) { _rate = rate; } public int GetRate() { return _rate; } }
class Program { static void Main(string[] args) { Employee kent = new Employee(3600); JobItem j1 = new JobItem(0, 5, true, kent); } }
创建一个子类,重构后:
class JobItem { private int _unitPrice; private int _quantity; private bool _isLabor; protected Employee _employee; protected JobItem(int unitPrice, int quantity, bool isLabor) { _unitPrice = unitPrice; _quantity = quantity; _isLabor = isLabor; } public JobItem(int unitPrice, int quantity) : this(unitPrice, quantity, false) { } public int GetTotalPrice() { return GetUnitPrice() * _quantity; } public virtual int GetUnitPrice() { return _unitPrice; } public int Quantity { get { return _quantity; } } protected virtual bool IsLabor() { return false; } }
class LaborItem:JobItem { public LaborItem(int unitPrice, int quantity, bool isLabor) : base(unitPrice, quantity, isLabor) { } public LaborItem(int quantity, Employee employee) : base(0, quantity, true) { _employee = employee; } public Employee Employee { get { return _employee; } } protected override bool IsLabor() { return true; } public override int GetUnitPrice() { return _employee.GetRate(); } }
客户端:
class Program { static void Main(string[] args) { Employee kent = new Employee(3600); JobItem j1 = new LaborItem(10, 5, true); JobItem j2 = new JobItem(10, 15); } }
七、Extract Superclass(提炼超类)
两个类有相似特性。为这两个类建立一个父类,将相同特性移至父类。
1、建立一个抽象父类。
2、运用Pull Up Field,Pull Up Method,Pull Up Constructor Boday逐一将子类共同元素上移到父类。
3、编译、测试。
八、Extract Interface(提炼接口)
若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。
1、新建一个接口。
2、在接口中声明待提炼类的共通操作。
3、让相关的类实现其接口。
4、调整客户端的类型声明,令其使用该接口。
class Employee { private int _rate; private bool _isSpecialSkill; Employee(int rate, bool isSpecialSkill) { _rate = rate; _isSpecialSkill = isSpecialSkill; } public int GetRate() { return _rate; } public bool HasSpecialSkill() { return _isSpecialSkill; } }
class TimeSheet { double Charge(Employee employee, int days) { int basic = employee.GetRate() * days; return (employee.HasSpecialSkill()) ? (basic * 1.05) : basic; } }
重构后:
interface IBillable { int GetRate(); bool HasSpecialSkill(); }
class TimeSheet { double Charge(<span style="color:#ff0000;">IBillable </span>employee, int days) { int basic = employee.GetRate() * days; return (employee.HasSpecialSkill()) ? (basic * 1.05) : basic; } }
九、Collapse Hierarchy(折叠继承体系)
父类与子类之间无太大区别,将它们合为一体。
1、选择你想移除的类:父类或子类。
2、使用Pull Up Field,Pull Up Method或Push Dwon Field,Push Down Method,把想移除的行为和属性搬移到另一个类中。
3、编译、测试。
4、调整原类的引用点,改为新类的引用。
5、移除源空类。
6、编译、测试。
十、Form Template Method(塑造模板函数)
你有一些子类,其中相应的函数以相同的顺序执行类的操作,但各个操作的细节上有所不同。将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同了。然后将原函数上移至父类。
1、在各个子类中分解目标函数,使分解后的各个函数不完全相同。
2、运用Pull Up Method将各个子类完全相同的函数上移父类。
3、对于那些完全不同的函数,实施Rename Method,使这些函数的签名完全相同。
4、编译、测试。
5、运用Pull Up Method将所有函数逐一上移到父类,并声明为抽象函数。
6、编译、测试。
7、移除子类中的原函数,编译、测试。
重构后:
十一、Replace Inheritance with Delegation(以委托取代继承)
某个子类只使用父类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存父类,调整子类函数,令它改而委托父类,然后去掉两者之间的继承关系。
1、在子类型新建一个字段,引用父类的一个实例。
2、修改子类所有函数,让它们不使用父类,转而使用字段。
3、编译、测试。
4、去除继承关系。
5、编译、测试。
十二、Replace Delegation with Inheritance(以继承取代委托)
你在两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数。让委托类继承受托类。
1、让委托端成为受托端的子类。
2、编译。
3、将受托字段设为该字段所处对象本身。
4、去掉简单的委托函数。
5、编译、测试。
6、把调用委托的代码改为对象本身。
7、移除受托字段。
class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } public string GetLastName() { return _name.SubString(_name.LastIndexOf(' ') +1); } }
class Employee { Person _person = new Person(); public override string ToString() { return "Emp:" + _person.GetLastName(); } }
重构后:
class Employee : Person { public override string ToString() { return "Emp:" + GetLastName(); } }
相关文章推荐
- 图说Java —— 理解Java机制最受欢迎的8幅图
- Python xml属性/节点/文本的增删改[xml.etree.ElementTree]
- Qt中splitter的使用
- 设计模式C++实现(3)——适配器模式
- Java回顾之Spring基础
- Java时间格式验证
- 为什么在C语言中 3<x<5无论x取什么值,最终结果都为1
- Java--数组
- Python文件操作注意事项
- 如何验证C语言中小数默认是double类型
- 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第55讲:PHP smarty模板自定义函数
- 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第54讲:PHP smarty模板内建函数
- python简单分割文件的方法
- 在C语言中如何确定一个数的溢出值是多少?
- Java复习第三天
- Java调用JNI的基本步骤(实现两数加法)
- Java学习笔记--------为什么不能这样用???
- Lua 学习备忘录3
- 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第53讲:PHP smarty模板配置及变量操作
- 利用PHP将部分内容用星号替换