这是重构之前的示例代码:
class Role
{
[Flags]
//标志枚举
public enum StateEnum
{
State1 = 0,
State2 = 2,
State3 = 4,
State4 = 8,
//一些状态
}
private StateEnum state = StateEnum.State1;
public StateEnum State
{
set { state = value; }
get { return state; }
}
private bool f1 = false;
private bool f2 = true;
public void Update()
{
if (!f1)
{
bool f3 = false;
//代码段6
switch (State)
{
case StateEnum.State1:
//代码段1
break;
case StateEnum.State2:
//代码段2
if (f3) {
//代码段8
}
break;
case StateEnum.State3:
//代码段3
break;
case StateEnum.State4:
//代码段4
break;
default:
//代码段5
break;
}
}
if (f2) {
//代码段7
}
}
}
其中,那些布尔型变量都是演示用的,注释写的代码段也是演示用的。
这段代码很可能出现了Large Class(过大的类)和Long Method(过长函数)坏味道,所以我们就可以用重构方法进行重构。
我们看,这个根据角色状态改变角色参数的switch结构在这个Update方法里,但是非常之乱套。我们先用Extract Method(提炼函数)重构手法进行重构,得到如下的结果:
class Role
{
[Flags]
//标志枚举
public enum StateEnum
{
State1 = 0,
State2 = 2,
State3 = 4,
State4 = 8,
//一些状态
}
private StateEnum state = StateEnum.State1;
public StateEnum State
{
set { state = value; }
get { return state; }
}
private bool f1 = false;
private bool f2 = true;
public void Update()
{
if (!f1)
{
bool f3 = false;
//代码段6
Switch(f3);
//位置1
}
if (f2) {
//代码段7
}
}
private void Switch(bool f3) {
switch (State)
{
case StateEnum.State1:
//代码段1
break;
case StateEnum.State2:
//代码段2
if (f3)
{
//代码段8
}
break;
case StateEnum.State3:
//代码段3
break;
case StateEnum.State4:
//代码段4
break;
default:
//代码段5
break;
}
//位置2
}
}
看到这个例子,原先的局部变量变成了提炼出来的函数的参数,在原地方调用这个新函数。
然后,我们使用Replace Conditional with Polymorphism(以多态取代条件表达式)重构手法和状态模式,把除了6和7以外的其他代码段都放进新的类里边。
先写一个新接口:
interface IState
{
void StateUpdate();
}
然后新建一个实现此接口的类:
class State1:IState
{
public void StateUpdate() {
//代码段1
}
}
在原先的Role类中新建一个IState类型字段iState,把case StateEnum.State1:中的代码改为iState = new State1();iState.StateUpdate();,这时再把iState.StateUpdate();移出switch结构,放到Switch(bool)方法最下边,也就是位置2,或者位置1也行。而对于case StateEnum.State2:这样的情况,可以给State2的构造方法增加一个参数,就可以了。
这时发现new状态的操作太多了,可以给这些状态类来个单例,单例模式很简单的,这里就不说了。至于State2,就要特殊情况特殊处理,可以在单例静态方法里根据一个静态字段进行判断,这个静态字段就是这个类里保存的f3,保存了上次产生的实例的参数,或者根据实际情况,也可以来个哈希表记录这个参数和对象实例的对应关系。或者也可以把IState接口换成一个抽象类,然后在其中写一个静态工厂函数,这个工厂函数的参数就是游戏角色的状态类型,这就用到了Replace Constructor with Factory Method(以工厂函数取代构造函数),这时State2的f3参数也可以放在这个抽象的基类里边,这些都看情况而定。
有关重构的内容,大家可以Google搜索,或者参考《重构:改善既有代码的设计》这本书。
5926

被折叠的 条评论
为什么被折叠?



