版权声明:请注明转发出处 https://blog.csdn.net/mafucun1988/article/details/89741613
《重构:改善既有代码的设计》中提到过很多重构方法,关于重新组织数据的方法有16种。本文介绍:
以字段取代子类 replace subclass with fields
- 名称:以字段取代子类 replace subclass with fields
- 概要:各个子类的唯一区别只在“返回常量数据”的函数身上。修改这些函数,使它们返回超类中的某个(新增)字段,然后销毁子类
- 动机:子类中只有常量函数,实在没有足够的存在价值。
- 做法:
- 对所有子类使用replace constuctor with factory method
- 如果有任何代码直接引用子类,令它引用超类
- 为超类声明一个protected构造函数,用以初始化这些新增字段
- 新建或修改子类构造函数,使它调用超类的新增构造函数
- 编译,测试
- 在超类中实现所有常量函数,令它们返回相应字段值,然后将该函数从子类中删掉
- 每删掉一个常量函数,编译并测试
- 子类中所有的常量函数都被删除后,使用inline method 将子类构造函数内联到超类的工厂函数中
- 编译,测试
- 将子类删掉
- 编译,测试
- 代码演示
修改之前的代码:
/////////////////////////.h
class Person2
{
public:
virtual bool isMale() = 0;
virtual char getCode() = 0;
};
class Male : public Person2
{
public:
bool isMale();
char getCode();
};
class Famale : public Person2
{
public:
bool isMale();
char getCode();
};
//////////////////////////.cpp
bool Male::isMale()
{
return true;
}
char Male::getCode()
{
return 'M';
}
bool Famale::isMale()
{
return false;
}
char Famale::getCode()
{
return 'F';
}
/////////////////////////////main.cpp
Person2 *kent = new Male();
qDebug() << "kent sex:" << kent->getCode();
1) 本文中,两个子类之间唯一的区别就是,它们以不同的方式实现了Person2所声明的纯虚函数getCode(),所以将这两个子类去掉。
2)使用 replace constructor with factory method,为每个子类建立一个工厂函数。
3)然后使用构造函数的地方都改为调用工厂函数
4)把两个子类都声明为private,防止其他函数使用它们
5)针对每个常量函数,在超类中声明一个对应的字段
6)针对每个常量函数,在超类中声明一个对应的字段,再为超类加上一个protected构造函数。为子类加上新构造函数,令它调用超类新增的构造函数。
7)我们可以在超类中加入访问这些字段的函数,并删除子类中的常量函数。
8)最后删除male 和 female两个子类
修改之后的代码:
/////////////////////////.h
class Person2
{
public:
//virtual bool isMale() = 0;
// virtual char getCode() = 0;
char getCode();
static Person2* createMale();
static Person2* createFemale();
protected:
Person2(bool isMale, char code);
private:
bool m_isMale;
char m_code;
};
//class Male : public Person2
//{
//public:
// Male();
//private:
//// bool isMale();
//// char getCode();
//};
//class Female : public Person2
//{
//public:
// Female();
//private:
//// bool isMale();
//// char getCode();
//};
//////////////////////////.cpp
//Male::Male():Person2 (true, 'M')
//{
//}
//bool Male::isMale()
//{
// return true;
//}
//char Male::getCode()
//{
// return 'M';
//}
//Female::Female() : Person2 (false, 'F')
//{
//}
//bool Female::isMale()
//{
// return false;
//}
//char Female::getCode()
//{
// return 'F';
//}
char Person2::getCode()
{
return m_code;
}
Person2 *Person2::createMale()
{
return new Person2(true, 'M');
}
Person2 *Person2::createFemale()
{
return new Person2(false, 'F');
}
Person2::Person2(bool isMale, char code)
{
m_isMale = isMale;
m_code = code;
}
///////////////////////////////main.cpp
Person2 *kent = Person2::createMale();
qDebug() << "kent sex:" << kent->getCode();