Replace Type Code with State/Strategy(以State/Strategy取代型别码)

你有一个type code,它会影响class的行为,但你无法使用subclassing.

以state object(专门用来描述状态的对象)取代type code。

Replace Type Code with State/Strategy

动机

本项重构和Replace Type Code with Subclasses很相似。但如果[type code值在对象生命期中发生变化],或者[其他原因使得宿主类不能被subclassing],你也可以使用本重构。本重构使用state模式或Strategy模式。

state模式和Strategy模式非常相似,因此你无论选择其中哪一个,重构过程都是相同的。[选择哪一个模式]并非问题关键所在,你只需要选择更适合特定情境的模式就行了。如果你打算完成本项重构之后再以Replace Conditional with Polymorphism简化一个算法,那么选择Strategy模式比较合适;如果你打算搬移与状态相关的数据,并且认为对象的状态会改变,就应该选择使用State模式。

作法

1. 用Self Encapsulate Field 将type code自我封装起来

2. 新建一个Class,根据type code的用途为它命名,这就是一个state object.

3. 为这个新建的class添加subclass,每个subclass对应一种type code。

比起逐一添加,一次性加入所有必要的subclass可能更简单些。

4. 在super class中建立一个抽象的查询函数,用以返回type code;在每个subclass中覆写该函数,返回确切的type code。

5. 编译

6. 在source class中建立一个值域,用以保存新建的state object。

7. 调整source class中负责查询type code的函数,将查询动作转发给state object。

8. 调整source class中为type code设值的函数,将一个恰当的state object subclass赋值给[保存state object]的那个值域。

9. 编译、测试。

 

我仍然使用这个既无聊又弱智的[雇员/薪资]例子。

class Employee {
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
Employee (int type) {
_type = type;
}

下面的代码展示这些type code的条件式:

int payAmount() {
switch (_type) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary + _commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}

假设这是一家激情四溢、积极进取的公司,他们可以将表现出色的工程师提升为经理。因此对象的type code是可以改变的,所以我不能使用subclassing来处理type code,和以前一样,我的第一步还是使用Self Encapsulate Field 将表示type code的值域自我封装起来

Employee (int type) {
setType (type);
}
int getType() {
return _type;
}
void setType(int arg) {
_type = arg;
}
int payAmount() {
switch (getType()) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary + _commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}

现在我需要声明一个state class,我把它声明为一个抽象类,并提供一个抽象函数,用以返回type code:

abstract class EmployeeType {
abstract int getTypeCode();
}

现在,我可以开始创建subclass了。

class Engineer extends EmployeeType {
int getTypeCode () {
return Employee.ENGINEER;
}
}
class Manager extends EmployeeType {
int getTypeCode () {
return Employee.MANAGER;
}
}
class Salesman extends EmployeeType {
int getTypeCode () {
return Employee.SALESMAN;
}
}

现在进行一次编译,前面所做的修改实在太平淡了,即时对我来说也太简单。现在我要修改type code的访问函数,实实在在的把这些subclass和Employee class联系起来

class Employee...
private EmployeeType _type;
int getType() {
return _type.getTypeCode();
}
void setType(int arg) {
switch (arg) {
case ENGINEER:
_type = new Engineer();
break;
case SALESMAN:
_type = new Salesman();
break;
case MANAGER:
_type = new Manager();
break;
default:
throw new IllegalArgumentException("Incorrect Employee
Code");
}
}

这意味我将在这里拥有一个switch语句,完成重构之后,这将是代码中唯一的switch语句。并且只在对象型别发生改变时才会被执行,我可以使用Replace Constructor with Factory Method针对不同的case子句建立相应的factory methods。我还可以立刻再使用Replace Conditional with Polymorphism,从而将其他的case子句全部消除。

最后,我喜欢将所有关于type code和subclass的知识都移到新的class,并以此结束Replace Type Code with State/Strategy。首先我把type code的定义拷贝到EmployeeType class中,在其中建立一个以生成恰当的EmployeeType 对象,并调整Employee class中为type code赋值的函数。

class Employee...
void setType(int arg) {
_type = EmployeeType.newType(arg);
}
class EmployeeType...
static EmployeeType newType(int code) {
switch (code) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
throw new IllegalArgumentException("Incorrect Employee
Code");
}
}
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;

然后,我删掉Employee中的type code定义,代之以一个指向EmployeeType的实例。

class Employee...
int payAmount() {
switch (getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary + _commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}

现在,万事俱备,我可以使用Replace Conditional with Polymorphism来处理payAmount函数了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值