处理概括关系之七 :Extract Superclass(提炼超类)
来源:互联网 发布:詹姆斯巅峰数据 编辑:程序博客网 时间:2024/05/19 22:44
两个classes 有相似特性(similar features)。
为这两个classes 建立一个superclass ,将相同特性移至superclass 。
动机(Motivation)
重复代码是系统中最主要的一种糟糕东西。如果你在不同的地方进行相同一件事 情,一旦需要修改那些动作时,你就得负担比你原本应该负担的更多事情。
重复代码的某种形式就是:两个classes 以相同的方式做类似的事情,或者以不同的方式做类似的事情。对象提供了一种简化这种情况的机制,那就是继承机制。但是,在建立这些具有共通性的classes 之前,你往往无法发现这样的共通性,因此你经常会在「具有共通性」的classes 存在之后,再幵始建立其间的继承结构。
另一种选择就是Extract Class。这两种方案之间的选择其实就是继承(Inheritance )和委托(delegation)之间的选择。如果两个classes 可以共享行为, 也可以共享接口,那么继承是比较简单的作法。如果你选错了,也总有 Replace Inheritance with Delegation 这瓶后悔药可吃。
作法(Mechanics)
范例:(Example)
下面例子中,我以Employee 表示「员工」,以Department 表示「部门」:
class Employee...
public Employee (String name, String id, int annualCost) {
_name = name;
_id = id;
_annualCost = annualCost;
}
public int getAnnualCost() {
return _annualCost;
}
public String getId(){
return _id;
}
public String getName() {
return _name;
}
private String _name;
private int _annualCost;
private String _id;
public class Department...
public Department (String name) {
_name = name;
}
public int getTotalAnnualCost(){
Enumeration e = getStaff();
int result = 0;
while (e.hasMoreElements()) {
Employee each = (Employee) e.nextElement();
result += each.getAnnualCost();
}
return result;
}
public int getHeadCount() {
return _staff.size();
}
public Enumeration getStaff() {
return _staff.elements();
}
public void addStaff(Employee arg) {
_staff.addElement(arg);
}
public String getName() {
return _name;
}
private String _name;
private Vector _staff = new Vector();
这里有两处共同点。首先,员工和部门都有名称(names);其次,它们都有年度成本(annual costs),只不过计算方式略有不同。我要提炼出一个superclass ,用以包容这些共通特性。第一步是新建这个superclass ,并将现有的两个classes 定义为其subclasses:
abstract class Party {}
class Employee extends Party...
class Department extends Party...
然后我开始把特性上移至superclass 。先实施Pull Up Field 通常会比较简单:
class Party...
protected String _name;
然后,我可以使用 Pull Up Method 把这个值域的取值函数(getter)也上移至superclass :
class Party {
public String getName() {
return _name;
}
我通常会把这个值域声明为private 。不过,在此之前,我需要先使用Pull Up Constructor Body,这样才能对_name 正确赋值:
class Party...
protected Party (String name) {
_name = name;
}
private String _name;
class Employee...
public Employee (String name, String id, int annualCost) {
super (name);
_id = id;
_annualCost = annualCost;
}
class Department...
public Department (String name) {
super (name);
}
Department.getTotalAnnualCost() 和 Employee.getAnnualCost() 两个函数的用途相同,因此它们应该有相同的名称。我先运用 Rename Method 把它们的名称改为相同:
class Department extends Party {
public int getAnnualCost(){
Enumeration e = getStaff();
int result = 0;
while (e.hasMoreElements()) {
Employee each = (Employee) e.nextElement();
result += each.getAnnualCost();
}
return result;
}
它们的函数本体仍然不同,因此我目前还无法使用 Pull Up Method。但是我 可以在superclass 中声明一个抽象函数:
abstract public int getAnnualCost()
这一步修改完成后,我需要观察两个subclasses 的用户,看看是否可以改变它们转而使用新的superclass 。用户之一就是Department 自身,它保存了一个Employee 对象群集。Department .getAnnualCost() 只调用群集内的元素(对象)的getAnnualCost() 函数,而该函数此刻乃是在Party class 声明的:
class Department...
public int getAnnualCost(){
Enumeration e = getStaff();
int result = 0;
while (e.hasMoreElements()) {
Party each = (Party) e.nextElement();
result += each.getAnnualCost();
}
return result;
}
这一行为暗示一种新的可能性:我可以用Composite 模式[Gang of Four] 来对待Department 和Employee ,这样就可以让一个Department 对象包容另—个Department 对象。这是一项新功能,所以这项修改严格来说不属于重构范围。如果用户恰好需要Composite 模式,我可以修改_staff 值域名字,使其更好地表现这一模式。这一修改还会带来其他相应修改:修改addStaff() 函数名称,并将该函数的参数型别改为Party class 。最后还需要把headCount() 函数变成一个递归调用。我的作法是在Employee 中建立一个headCount() 函数,让它返回1;再使用Substitute Algorithm 修改Department 的headCount() 函数,让它总和(add)各部门的headCount() 调用结果。
- 处理概括关系之七 :Extract Superclass(提炼超类)
- 处理概括关系之六 :Extract Subclass(提炼子类)
- 处理概括关系之八 :Extract Interface(提炼接口)
- 11.7 extract superclass (提炼超类)
- Extract Class(提炼类)
- Extract Class(提炼类)
- 重构方法之处理概括关系(继承关系)
- 在对象之间搬移特性之三 :Extract Class(提炼类)
- 7.3extract class(提炼类)
- Extract Subclass(提炼子类)
- Extract Interface(提炼接口)
- 处理概括关系(一)
- 处理概括关系(二)
- 重构之处理概括关系
- 6.1 Extract Method(提炼函数)
- 6、处理概括关系
- 处理概括关系
- 处理概括关系之九 :Collapse Hierarchy(折叠继承关系)
- Android引入第三方jar包的方法
- debian 64位系统中添加对32位的支持
- PostgreSQL+PostGIS的使用
- MTK MT65XX平台开发分支下配置多个项目的规范说明
- VC下如何使用GDI+进行图像程序设计
- 处理概括关系之七 :Extract Superclass(提炼超类)
- C++使用tinyXml读取XML
- Table之CSS控制Table内外边框,颜色,大小,样式变化更简单
- install JIRA Windows
- TCHAR 拼接字符串
- 处理概括关系之八 :Extract Interface(提炼接口)
- C++中extern “C”含义深层探索
- td或div 中同时有文字和按钮、输入框 垂直居中
- string资源动态的插入内容