佳佳的博客
Menu
首页
《重构》 12. 处理继承关系
Posted by
佳佳
on 2020-06-03
IT
《重构》
读书笔记
<!-- # 《重构》 12. 处理继承关系 --> <!-- refactoring-12-handling-inheritance-relationships --> ## 12.1 函数上移(Pull Up Method) **反向重构**:*函数下移(Push Down Method)* 避免重复代码是很重要的。 **重构前**: ```csharp class Employee { } class Salesman : Employee { public void Rest() { } } class Engineer : Employee { public void Rest() { } } ``` **重构后**: ```csharp class Employee { public void Rest() { } } class Salesman : Employee { } class Engineer : Employee { } ``` ## 12.2 字段上移(Pull Up Field) **反向重构**:*字段下移(Push Down Field)* 跟*函数上移*类似。 **重构前**: ```csharp class Employee { } class Salesman : Employee { public string Name { get; set; } } class Engineer : Employee { public string Name { get; set; } } ``` **重构后**: ```csharp class Employee { public string Name { get; set; } } class Salesman : Employee { } class Engineer : Employee { } ``` ## 12.3 构造函数本体上移(Pull Up Constructor Body) **重构前**: ```csharp class Party { } class Employee : Party { public Employee(int id, string name, decimal monthlyCost) { Id = id; Name = name; MonthlyCost = monthlyCost; } public int Id { get; set; } public string Name { get; set; } public decimal MonthlyCost { get; set; } } ``` **重构后**: ```csharp class Party { public Party(string name) { Name = name; } public string Name { get; set; } } class Employee : Party { public Employee(int id, string name, decimal monthlyCost) : base(name) { Id = id; MonthlyCost = monthlyCost; } public int Id { get; set; } public decimal MonthlyCost { get; set; } } ``` ## 12.4 函数下移(Push Down Method) **反向重构**:*函数上移(Pull Up Method)* **重构前**: ```csharp class Employee { private int _quota; public int Quota() { return _quota; } } class Engineer : Employee { } class Salesman : Employee { } ``` **重构后**: ```csharp class Employee { } class Engineer : Employee { } class Salesman : Employee { private int _quota; public int Quota() { return _quota; } } ``` ## 12.5 字段下移(Push Down Field) **反向重构**:*字段上移(Pull Up Field)* **重构前**: ```csharp class Employee { public int Quota { get; set; } } class Engineer : Employee { } class Salesman : Employee { } ``` **重构后**: ```csharp class Employee { } class Engineer : Employee { } class Salesman : Employee { public int Quota { get; set; } } ``` ## 12.6 以子类取代类型码(Replace Type Code with Subclasses) **包含旧重构**:*以 State/Strategy 取代类型码(Replace Type Code with State/Strategy)* **包含旧重构**:*提炼子类(Extract Subclass)* **反向重构**:*移除子类(Remove Subclass)* **重构前**: ```csharp Employee CreateEmployee(string name, string type) { return new Employee(name, type); } ``` **重构后**: ```csharp Employee CreateEmployee(string name, string type) { switch (type) { case "engineer": return new Engineer(name); case "saleman": return new Saleman(name); case "manager": return new Manager(name); default: return new Employee(name); } } ``` ## 12.7 移除子类(Remove Subclass) **曾用名**:*以字段取代子类(Replace Subclass with Fields)* **反向重构**:*以子类取代类型码(Replace Type Code with Subclasses)* 子类存在着就有成本,所以如果子类的用处太少,就不值得存在了。 **重构前**: ```csharp class Person { public virtual string GenderCode => "X"; } class Male : Person { public override string GenderCode => "M"; } class Female : Person { public override string GenderCode => "F"; } ``` **重构后**: ```csharp class Person { public string GenderCode { get; set; } } ``` ## 12.8 提炼超类(Extract Superclass) 如果看见两个在做相似的事,可以利用基本的继承机制把他们的相似之处提炼到超类。 **重构前**: ```csharp class Department { public string Name { get; set; } public int HeadCount { get; set; } public decimal MonthlyCost { get; set; } public decimal TotalAnnualCost() { return decimal.Multiply(decimal.Multiply(MonthlyCost, new decimal(12)), new decimal(1.2)); } } class Employee { public string Name { get; set; } public int Id { get; set; } public decimal MonthlyCost { get; set; } public decimal AnnualCost() { return decimal.Multiply(MonthlyCost, new decimal(14)); } } ``` **重构后**: ```csharp class Party { public string Name { get; set; } public decimal MonthlyCost { get; set; } public virtual decimal AnnualCost() { return decimal.Multiply(MonthlyCost, new decimal(12)); } } class Department : Party { public int HeadCount { get; set; } public override decimal AnnualCost() { return decimal.Multiply(base.AnnualCost(), new decimal(1.2)); } } class Employee : Party { public int Id { get; set; } public override decimal AnnualCost() { return decimal.Add(base.AnnualCost(), decimal.Multiply(MonthlyCost, new decimal(2))); } } ``` ## 12.9 折叠继承体系(Collapse Hierarchy) 若一个类与其超类已经没多大差别,则其不值得再作为独立的类存在。 **重构前**: ```csharp class Employee { } class Saleman : Employee { } ``` **重构后**: ```csharp class Employee { } ``` ## 12.10 以委托取代子类(Replace Subclass with Delegate) 继承是个很强大的机制,但也有其短板:大多数语言只允许但继承;继承给类之间引入了非常紧密的联系。 使用委托可以解决上述问题。 “对象组合优于类继承”(“组合”跟“委托”是同一回事)。 **重构前**: ```csharp class Order { private Warehouse _warehouse; public virtual int DaysToShip { get { return _warehouse.DaysToShip; } } } class PriorityOrder : Order { private PriorityPlan _priorityPlan; public override int DaysToShip { get { return _priorityPlan.DaysToShip; } } } ``` **重构后**: ```csharp class Order { private Warehouse _warehouse; private PriorityPlanDelegate _piorityPlanDelegate; public int DaysToShip { get { return _piorityPlanDelegate != null ? _piorityPlanDelegate.DaysToShip : _warehouse.DaysToShip; } } } class PriorityPlanDelegate { private PriorityPlan _priorityPlan; public int DaysToShip { get { return _priorityPlan.DaysToShip; } } } ``` ## 12.11 以委托取代超类(Replace Superclass with Delegate) **曾用名**:*以委托取代继承(Replace Inheritance with Delegate)* 如果超类的一些函数对于子类并不适用,就说明不应该通过继承来获得超类的功能。 合理的继承关系还有一个重要特征:子类的所有实例都应该是超类的实例,通过超类的接口来使用子类的实例应该完全不出问题。 首先(尽量)使用继承,如果发现继承有问题,再使用 *以委托取代超类* 。 **重构前**: ```csharp class List { // ... } class Stack : List { // ... } ``` **重构后**: ```csharp class List { // ... } class Stack { List _stoarge; public Stack() { _stoarge = new List(); } // ... } ``` ## 附1. 引用 1. [《重构:改善既有代码的设计》][1] -- 马丁·福勒(*Martin Fowler*) [1]: https://union-click.jd.com/jdc?e=&p=AyIGZRhaEwAQBFUZXBIyEgRREl4QChs3EUQDS10iXhBeGlcJDBkNXg9JHU4YDk5ER1xOGRNLGEEcVV8BXURFUFdfC0RVU1JRUy1OVxUBFg5QHlMcMloDXR8JHXtmYiNlWEBFeV1UUjxnS0QLWStaJQITBlYbXB0LFQJlK1sSMkBpja3tzaejG4Gx1MCKhTdUK1sRCxQBVxtdFAcTB1crXBULIloNXwZBXUReEStrJQEiN2UbaxYyUGlUE1xGBhFQBR5bFVUXVAdOU0dWGwFdTwtAAkZTVE9fRTIQBlQfUg%3D%3D (《重构:改善既有代码的设计》)
版权声明:原创文章,未经允许不得转载。
https://www.liujiajia.me/2020/6/3/refactoring-12-handling-inheritance-relationships
“Buy me a nongfu spring”
« 《Java 核心技术 卷Ⅰ》 第1章 Java 程序设计概述
《重构》 11. 重构API »
昵称
*
电子邮箱
*
回复内容
*
(回复审核后才会显示)
提交
目录
AUTHOR
刘佳佳
江苏 - 苏州
软件工程师