您的位置:首页 > 编程语言

改善代码设计 —— 处理概括关系(Dealing with Generalization)

2011-07-24 18:30 218 查看

1. Pull Up Field (提升值域)

解释:


如果发现每个子类都拥有相同的某个值域, 那么使用 Pull Up Field 将这个值域提升到父类中去.


冲动前:



冲动后:



2. Pull Up Method (提升函数)

解释:


如果每个子类都有相同的某个函数, 这个函数做同样的事情, 而且结果也相同, 那么使用 Pull Up Method 将这个函数提升到父类中去.


冲动前:



冲动后:



3. Pull Up Constructor Body (提升构造函数)

解释:


特别要注意每个子类中重复的代码, 如果可能的话尽量将它们提炼成方法并搬到父类中去. 对于子类的构造函数, 我们需要找出相同的部分, 用这些相同的部分组成父类的构造函数.

如下面的例子, 如果不光 Salesman, 还有 Engineer 等等类别的员工在构造他们的时候都需要 name 和 level 属性, 可以考虑使用 Pull Up Constructor Body 将设置这两个属性提升到父类的构造函数中去.


冲动前:

00
class
Employee
01
{
02
public
string
Name {
get
;
set
;}
03
public
int
Level {
get
;
set
;}
04
//...
05
}
06
class
Salesman : Employee
07
{
08
public
string
Hobby {
get
;
set
;}
09
10
public
Salesman(
string
name,
int
level,
string
hobby)
11
{
12
this
.Name = name;
13
this
.Level = level;
14
this
.Hobby = hobby;
15
}
16
//...
17
}
18
//...

冲动后:

00
class
Employee
01
{
02
public
string
Name {
get
;
set
;}
03
public
int
Level {
get
;
set
;}
04
05
public
Employee(
string
name,
int
level)
06
{
07
this
.Name = name;
08
this
.Level = level;
09
}
10
//...
11
}
12
class
Salesman : Employee
13
{
14
public
string
Hobby {
get
;
set
;}
15
16
public
Salesman(
string
name,
int
level,
string
hobby):
base
(name,level)
17
{
18
this
.Hobby = hobby;
19
}
20
//...
21
}
22
//...

4. Push Down Method (降低函数)

解释:


父类里有某个函数只与一部分子类有关, 并不是与所有的子类都有关, 使用 Push Down Method 重构手段将这些函数放到使用它们的子类中去, 而不要放到父类中.


冲动前:



冲动后:



5. Push Down Field (降低值域)

解释:


与 Push Down Method 描述的问题类似, 父类中如果某个值域并不是对于每个子类都有用的, 应该把它放到需要它的子类中去.


6. Extract Subclass (提炼子类)

解释:


我们产生了类的一些实例, 但并不是每个实例都用得到类中所有的特性, 往往这是类中功能设计过多的原因造成的. 尝试从这个类中提炼出一些子类, 子类中的功能应该划分得很明确.


7. Extract Superclass (提炼父类)

解释:


如果你发现有两个类, 他们有很多相同的特性, 尝试找出两个类中相同的特性, 如果你能找到一个合适的理由让这两个类继承自一个父类, 从而你可以提炼出这个父类, 父类中包含那两个类中相同的部分.


8. Extract Interface (提炼接口)

解释:


类与类之间经常会相互调用, 比如 ClassA 的某个函数里需要 ClassB 里的某个值域或者某个函数的返回值, 因此我将整个 ClassB 作为参数传递给 ClassA 的这个函数, 这意味着 ClassA 的这个函数能够调用 ClassB 里所有的功能, 可不可以给 ClassA 的这个函数划定一个特定的职能呢? 让它只能做某些事情, 而避免其它 "越权行为". 有句话常被人说起 ——使用接口来降低耦合性, 这就是 Extract Interface 的功劳.

这条重构手段经常被使用到, 主要解决类对另一个类的依赖问题, 降低了耦合性.


冲动前:

00
class
Xml
01
{
02
public
void
Read()
03
{
04
//...
05
}
06
public
void
Translate()
07
{
08
//...
09
}
10
//some other methods
11
}
12
class
WeatherService
13
{
14
public
string
GetWeather(Xml xml)
15
{
16
xml.Read();
17
xml.Translate();
18
//other code, but without xml object
19
}
20
//some other methods
21
}

冲动后:

00
interface
IOperation
01
{
02
void
Read();
03
void
Translate();
04
}
05
class
Xml : IOperation
06
{
07
public
void
Read()
08
{
09
//...
10
}
11
public
void
Translate()
12
{
13
//...
14
}
15
//some other methods
16
}
17
class
WeatherService
18
{
19
public
string
GetWeather(IOperation operation)
20
{
21
operation.Read();
22
operation.Translate();
23
//other code, but without xml object
24
}
25
//some other methods
26
}
注意代码高亮的那行已经变成调用接口, 而不是仅依赖调用 Xml 类的实例, 对于单个类实现这样的接口并不是很有价值, 如果很多类都实现了同样的接口, 这将是很有用的事情.

9. Collapse Hierarchy (去掉不必要的继承关系)

解释:


庞大的继承体系很容易变得复杂, 理清父类与子类它们各自的职能是非常重要的, 你很有可能会发现不必要的子类, 那么使用 Pull Up Field 和 Pull Up Method 将它干掉.


10. Replace Inheritance with Delegation (用委派取代继承)

解释:


如果你想让 ClassA 使用某个类 (如 ClassB) 的某个函数, 就让 ClassA 继承自 ClassB, 这将是一个多么糟糕的设计! 你可以在 ClassA 中包含一个 ClassB 的值域, 通过这个值域调用你需要的函数, 这个值域就是"委派", 而你这时可以去掉 ClassA 和 ClassB 之间不该存在的继承关系了.


11. Replace Delegation with Inheritance (用继承代替委派)

解释:


这一条与 Replace Inheritance with Delegation 正好相反, 如果你需要使用委派中的所有函数, 这时你就应该想想它们之间是不是存在继承关系.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: