《重构:改善既有代码的设计》中提到过很多重构方法,关于重新组织数据的方法有16种。本文介绍:
以类取代类型码 replace type code with class
- 名称:以类取代类型码 replace type code with class
- 概要:类中有一个数值类型码,但它并不影响类的行为,以一个新的类替换改数值类型码
- 动机:类型码作为函数参数,编译器无法进行类型检验。
- 做法:
- 为类型码建立一个类。这个类需要一个用以记录类型码的字段,其类型和类型码相同,并有取值函数。此外还应该用一组静态变量保存允许被创建的实例,并以一个静态函数根据原本的类型码返回合适的实例
- 修改源类实现,让它使用新建的类。维持原先以类型码为基础的函数接口,但改变静态字段,以新建的类 产生代码。然后,修改类型码相关函数,让它们也从新建的类中获取类型码
- 编译,测试
- 对于源类中每一个使用类型码的函数,相应建立一个函数,让新函数使用新建的类。建立“以新类实例为自变量”的函数,用以替换原先“直接以类型码为参数”的函数。建立一个“返回新类实例”的函数,用以替换原先“直接返回类型码”的函数。建立新函数前,使用rename method修改原函数名称,明确指出哪些函数仍然使用旧式的类型码。
- 逐一修改源类用户,让它们使用新接口
- 编译,测试
- 删除使用类型码的旧接口,并删除保存旧类型码的静态变量
- 编译,测试
- 代码演示
修改之前的代码:
/.h
class Human
{
public:
static const int O = 0;
static const int A = 1;
static const int B = 2;
static const int AB = 3;
Human(int bloodGroup);
int getBloodGroup() const;
void setBloodGroup(int bloodGroup);
private:
int m_bloodGroup;
};
//.cpp
Human::Human(int bloodGroup)
{
m_bloodGroup = bloodGroup;
}
int Human::getBloodGroup() const
{
return m_bloodGroup;
}
void Human::setBloodGroup(int bloodGroup)
{
m_bloodGroup = bloodGroup;
}
//main.cpp
Human *human = new Human(Human::A);
qDebug() << "human bloodGroup = " << human->getBloodGroup();
1) 新建bloodGroup类,用来表示血型
2)把person类中的类型码改为使用bloodGroup类。这样就拥有了运行期检验能力
3) 修改person,以bloodgroup表示类型码,而不再使用整数
4) 删掉原本使用整数类型的哪些旧的取值函数,构造函数,静态变量和设置函数
修改之后的代码:
/.h
class BloodGroup
{
public:
BloodGroup(int code);
int getCode() const;
static BloodGroup* Code(int code);
static BloodGroup *O;
static BloodGroup *A;
static BloodGroup *B;
static BloodGroup *AB;
static BloodGroup *m_value[4];
private:
int m_code;
};
class Human
{
public:
// static const int O;
// static const int A;
// static const int B;
// static const int AB;
Human(BloodGroup* bloodGroup);
BloodGroup* getBloodGroup() const;
void setBloodGroup(BloodGroup* bloodGroup);
private:
BloodGroup* m_bloodGroup;
};
//.cpp
BloodGroup* BloodGroup::O = new BloodGroup(0);
BloodGroup* BloodGroup::A = new BloodGroup(1);
BloodGroup* BloodGroup::B = new BloodGroup(2);
BloodGroup* BloodGroup::AB = new BloodGroup(3);
BloodGroup* BloodGroup::m_value[4] = {O, A, B, AB};
//const int Human::O= BloodGroup::O->getCode();
//const int Human::A= BloodGroup::A->getCode();
//const int Human::B= BloodGroup::B->getCode();
//const int Human::AB= BloodGroup::AB->getCode();
Human::Human(BloodGroup* bloodGroup)
{
m_bloodGroup = bloodGroup;
}
BloodGroup* Human::getBloodGroup() const
{
return m_bloodGroup;
}
void Human::setBloodGroup(BloodGroup* bloodGroup)
{
m_bloodGroup = bloodGroup;
}
BloodGroup::BloodGroup(int code)
{
m_code = code;
}
int BloodGroup::getCode() const
{
return m_code;
}
BloodGroup* BloodGroup::Code(int code)
{
return m_value[code];
}
//main.cpp
Human *human = new Human(BloodGroup::A);
qDebug() << "human bloodGroup = " << human->getBloodGroup()->getCode();