1 Replace Type Code with Class
1.0 重构前
// Person.h
#pragma once
class Person
{
public:
static int O;
static int A;
private:
int bloodType;
public:
Person(int bloodType_);
void setBloodType(int bloodType_);
int getBloodType();
};
// Person.cpp
#include "Person.h"
int Person::O = 0; // Note: static var/func 定义处不能再用 static
int Person::A = 1;
Person::Person(int bloodType_)
: bloodType(bloodType_) {}
void Person::setBloodType(int bloodType_)
{
bloodType = bloodType_;
}
int Person::getBloodType()
{
return bloodType;
}
// main.cpp
#include "Person.h"
int main()
{
Person* person = new Person(Person::A);
int bloodType = person->getBloodType();
person->setBloodType(Person::O);
}
1.1 重构 1
// Person.h
#pragma once
#include "BloodType.h"
class Person
{
private:
BloodType* bloodType;
public:
Person(BloodType* bloodType_);
void setBloodType(BloodType* bloodType_);
BloodType* getBloodType();
~Person();
};
// BloodType.h
#pragma once
#include <vector>
class BloodType
{
public:
// (1) Note1: 创建静态对象用工厂函数, 保证了只有合法的 静态对象 才会被创建
static BloodType* O;
static BloodType* A;
private:
int typeCode;
public:
BloodType(int typeCode_);
private: // (2) Note2: Client not use
// (3) 一组静态变量 保存允许被创建的 object
static std::vector<BloodType*> bloodTypeVec;
// (4) 取一组静态变量中的1个, 对应用静态函数
static BloodType* getBloodType(int typeCode_);
int getTypeCode();
};
void destoryGlobal();
// Person.cpp
#include "Person.h"
Person::Person(BloodType* bloodType_)
: bloodType(bloodType_) {}
void Person::setBloodType(BloodType* bloodType_)
{
bloodType = bloodType_;
}
BloodType* Person::getBloodType()
{
return bloodType;
}
Person::~Person()
{
bloodType = nullptr; // (5) Note3: 静态对象的释放 由 client 最后全局处理
}
// BloodType.cpp
#include "BloodType.h"
BloodType* BloodType::O = new BloodType(0);
BloodType* BloodType::A = new BloodType(1);
std::vector<BloodType*> BloodType::bloodTypeVec =
{ O, A };
BloodType::BloodType(int typeCode_)
: typeCode(typeCode_) { }
BloodType*
BloodType::getBloodType(int typeCode_)
{
return bloodTypeVec[typeCode_];
}
int BloodType::getTypeCode()
{
return typeCode;
}
void destoryGlobal()
{
if (BloodType::O)
{
delete BloodType::O;
BloodType::O = nullptr;
}
if (BloodType::A)
{
delete BloodType::A;
BloodType::A = nullptr;
}
}
// main.cpp
#include "Person.h"
int main()
{
Person* person = new Person(BloodType::A);
BloodType* bloodType = person->getBloodType();
person->setBloodType(BloodType::O);
if (person)
delete person;
destoryGlobal();
}
2 Relpace Type Code with Subclass
2.0 重构前
// Employee.h
#pragma once
class Employee
{
private:
int typeCode;
int monthlySalary;
int bonus; // only Manager has
public:
static const int ENGINEER;
static const int MANAGER;
public:
Employee(int typeCode_);
int payAmount();
};
// Employee.cpp
#include "Employee.h"
#include <iostream>
const int Employee::ENGINEER = 0;
const int Employee::MANAGER = 1;
Employee::Employee(int typeCode_)
:typeCode(typeCode_), monthlySalary(20000), bonus(10000) {}
int Employee::payAmount()
{
switch (typeCode) // Note: typeCode doesn't changed
{
case ENGINEER:
return monthlySalary;
case MANAGER:
return monthlySalary + bonus;
default:
return 0;
}
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = new Employee(Employee::ENGINEER);
int pay = pEmployee->payAmount();
delete pEmployee;
pEmployee = new Employee(Employee::MANAGER);
pay = pEmployee->payAmount();
delete pEmployee;
pEmployee = nullptr;
}
2.1 step1-Refactor2+Refactor4
// Employee.h
#pragma once
class Employee
{
private:
// (1) Note1: remove TypeCode field
int monthlySalary;
int bonus; // only Manager has
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
public:
Employee();
// (2) Note2: Refactor4- Relpace Ctor with Factory Method
static Employee* create(int typeCode_);
// (3) Note3: Conditional func add typeCodePara
int payAmount(int typeCode_); // arg = getTypeCode()
// (4) Note4: Let Subclass tell its typeCode
virtual int getTypeCode() = 0;
};
// Engineer.h
#pragma once
#include "Employee.h"
class Engineer: public Employee
{
public:
int getTypeCode();
};
// Manager.h
#pragma once
#include "Employee.h"
class Manager: public Employee
{
public:
int getTypeCode();
};
// EmployeeFactor.cpp
#include "Employee.h"
#include "Engineer.h"
#include "Manager.h"
Employee*
Employee::create(int typeCode_)
{
switch (typeCode_)
{
case ENGINEER:
return new Engineer();
case MANAGER:
return new Manager();
default:
return nullptr;
}
}
// Employee.cpp
#include "Employee.h"
#include <iostream>
Employee::Employee()
:monthlySalary(20000), bonus(10000) {}
int Employee::payAmount(int typeCode_)
{
switch (typeCode_) // Note: typeCode doesn't changed
{
case ENGINEER:
return monthlySalary;
case MANAGER:
return monthlySalary + bonus;
default:
return 0;
}
}
// Engineer.cpp
#include "Engineer.h"
int Engineer::getTypeCode()
{
return Employee::ENGINEER;
}
// Manager.cpp
#include "Manager.h"
int Manager::getTypeCode()
{
return Employee::MANAGER;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = Employee::create(Employee::ENGINEER);
int pay = pEmployee->payAmount(pEmployee->getTypeCode() );
delete pEmployee;
pEmployee = Employee::create(Employee::MANAGER);
pay = pEmployee->payAmount(pEmployee->getTypeCode() );
delete pEmployee;
pEmployee = nullptr;
}
2.2 step2-Refactor5
// Employee.h
#pragma once
class Employee
{
private:
int monthlySalary;
int bonus; // only Manager has
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
public:
Employee();
static Employee* create(int typeCode_);
// (1) Note1: Conditional func changed to pvf,
// no longer need typeCodePara
// no longer need default branch
virtual int payAmount() = 0;
// (2) Note2: original TypeCode attached Class add field getFunc,
// used by subClass's vf: payAmount()
int getMonthlySalary();
int getBonus();
// (3) Note3: getTypeCode() not need in this demoProgram
virtual int getTypeCode() = 0;
};
// Engineer.h
#pragma once
#include "Employee.h"
class Engineer: public Employee
{
public:
virtual int payAmount();
int getTypeCode();
};
// Manager.h
#pragma once
#include "Employee.h"
class Manager: public Employee
{
public:
virtual int payAmount();
int getTypeCode();
};
// EmployeeFactor.cpp
#include "Employee.h"
#include "Engineer.h"
#include "Manager.h"
Employee*
Employee::create(int typeCode_)
{
switch (typeCode_)
{
case ENGINEER:
return new Engineer();
case MANAGER:
return new Manager();
default:
return nullptr;
}
}
// Employee.cpp
#include "Employee.h"
#include <iostream>
Employee::Employee()
:monthlySalary(20000), bonus(10000) {}
int Employee::getMonthlySalary()
{
return monthlySalary;
}
int Employee::getBonus()
{
return bonus;
}
// Engineer.cpp
#include "Engineer.h"
int Engineer::payAmount()
{
return getMonthlySalary();
}
int Engineer::getTypeCode()
{
return Employee::ENGINEER;
}
// Manager.cpp
#include "Manager.h"
int Manager::payAmount()
{
return getMonthlySalary() + getBonus();
}
int Manager::getTypeCode()
{
return Employee::MANAGER;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = Employee::create(Employee::ENGINEER);
// Note: Client vf payAmount() no longer need typeCodePara
int pay = pEmployee->payAmount();
delete pEmployee;
pEmployee = Employee::create(Employee::MANAGER);
pay = pEmployee->payAmount();
delete pEmployee;
pEmployee = nullptr;
}
2.3 step3-Refactor7: Push Down Field & Method 将只与特定子类相关
的字段和函数下推
到相关子类
只变动4个文件: Employee.h/cpp Manager.h/cpp
// Employee.h
#pragma once
class Employee
{
private:
// (1) Note1: Push Down Field: Mamager special
int monthlySalary;
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
public:
Employee();
static Employee* create(int typeCode_);
virtual int payAmount() = 0;
int getMonthlySalary();
// (2) Note2: Push Down Method: Mamager special
virtual int getTypeCode() = 0;
};
// Manager.h
#pragma once
#include "Employee.h"
class Manager: public Employee
{
private:
int bonus; // only Manager has
public:
Manager();
virtual int payAmount();
int getBonus(); // only Manager has
int getTypeCode();
};
// Employee.cpp
#include "Employee.h"
#include <iostream>
Employee::Employee()
:monthlySalary(20000) {}
int Employee::getMonthlySalary()
{
return monthlySalary;
}
// Manager.cpp
#include "Manager.h"
Manager::Manager(): bonus(10000) {}
int Manager::payAmount()
{
return getMonthlySalary() + getBonus();
}
int Manager::getBonus()
{
return bonus;
}
int Manager::getTypeCode()
{
return Employee::MANAGER;
}
3 以 State/Strategy 取代 类型码(TypeCode)
3.0 重构前
// Employee.h
#pragma once
class Employee
{
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
private:
int type;
int monthlySalary;
int bonus;
public:
Employee(int typeCode_);
int payAmount(); // (1) Note1: Conditional func, getType() to calculate typeCode
int getType();
void setType(int typeCode_);
};
// Employee.cpp
#include "Employee.h"
Employee::Employee(int typeCode_)
: type(typeCode_), monthlySalary(20000), bonus(10000){}
int Employee::payAmount()
{
switch (getType() ) // (2) Note2: typeCode can be change
{
case ENGINEER:
return monthlySalary;
case MANAGER:
return monthlySalary + bonus;
default:
return 0;
}
}
int Employee::getType()
{
return type;
}
void Employee::setType(int typeCode_)
{
type = typeCode_;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = new Employee(Employee::MANAGER);
int pay = pEmployee->payAmount();
pEmployee->setType(Employee::ENGINEER);
pay = pEmployee->payAmount();
}
3.1 重构 3
: 类型码 field 换为 新类的指针 EmployeeType*
// Employee.h
#pragma once
#include "EmployeeType.h" // (1.1) associate / depend
class Employee
{
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
private:
EmployeeType* type; // (1) Note1: type from int(typeCode) to typeClassPtr
int monthlySalary;
int bonus;
public:
Employee(int typeCode_); // (2) Note2: Ctor call setType(.)
void setType(int typeCode_);
int payAmount();
int getType(); // (3) Note3: getType() turn to call type->getTypeCode(); and used in Conditional func payAmount()
~Employee();
};
// EmployeeType.h
#pragma once
class EmployeeType
{
public:
virtual int getTypeCode() = 0;
};
// Engineer.h
#pragma once
#include "EmployeeType.h"
class Engineer: public EmployeeType // (5) Note5: subClass moved to newClass`
{
public:
int getTypeCode();
};
// Manager.h
#pragma once
#include "EmployeeType.h"
class Manager : public EmployeeType
{
public:
int getTypeCode();
};
// Employee.cpp
#include "Engineer.h"
#include "Manager.h"
#include "Employee.h"
Employee::Employee(int typeCode_)
: type(nullptr), monthlySalary(20000), bonus(10000)
{
setType(typeCode_);
}
void Employee::setType(int typeCode_)
{
if (type)
{
delete type;
type = nullptr;
}
switch (typeCode_) // after refactor, code only has one switch/if, and setType is called when obj ctor or typeCode change
{
case ENGINEER:
type = new Engineer();
break;
case MANAGER:
type = new Manager();
break;
default:
type = nullptr;
}
}
int Employee::payAmount()
{
switch (getType() ) // (4) Note4: typeCode can be change
{
case ENGINEER:
return monthlySalary;
case MANAGER:
return monthlySalary + bonus;
default:
return 0;
}
}
int Employee::getType()
{
return type->getTypeCode();
}
Employee::~Employee()
{
if (type)
delete type;
}
// Engineer.cpp
#include "Employee.h"
#include "Engineer.h"
int Engineer::getTypeCode()
{
return Employee::ENGINEER;
}
// Manager.cpp
#include "Employee.h"
#include "Manager.h"
int Manager::getTypeCode()
{
return Employee::MANAGER;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = new Employee(Employee::MANAGER);
int pay = pEmployee->payAmount();
pEmployee->setType(Employee::ENGINEER);
pay = pEmployee->payAmount();
delete pEmployee;
}
3.2 重构 6
: 将 类型码 info(类型码枚举值/编译期常量 ENGINEER / MANAGER)
和 子类(Engineer / Manager) info
均移到 新类 EmployeeType
// Employee.h
#pragma once
#include "EmployeeType.h"
class Employee
{
private:
EmployeeType* type;
int monthlySalary;
int bonus;
public:
// (1) Note1: Ctor(int typeCode_) -> setType(int typeCode_) -> newType(int typeCode)
Employee(int typeCode_);
void setType(int typeCode_);
int payAmount();
int getType();
~Employee();
};
// EmployeeType.h
#pragma once
class EmployeeType
{
public:
// (3) Note3: typeCode enumValue moved to newClass
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
public:
// (2) Note2: Factory Method, provide subClassObj,
// `subClass info( return new Engineer() )` all moved to EmployeeType
static EmployeeType* newType(int typeCode);
virtual int getTypeCode() = 0;
};
// Engineer.h
#pragma once
#include "EmployeeType.h"
class Engineer: public EmployeeType
{
public:
int getTypeCode();
};
// Manager.h
#pragma once
#include "EmployeeType.h"
class Manager: public EmployeeType
{
public:
int getTypeCode();
};
// EmployeeTypeFactory.cpp
#include "EmployeeType.h"
#include "Engineer.h"
#include "Manager.h"
EmployeeType*
EmployeeType::newType(int typeCode_)
{
switch (typeCode_) // after refactor, code only has one switch/if, and setType is called when obj ctor or typeCode change
{
case ENGINEER:
return new Engineer();
case MANAGER:
return new Manager();
default:
return nullptr;
}
}
// Employee.cpp
#include "Employee.h"
Employee::Employee(int typeCode_)
: type(nullptr), monthlySalary(20000), bonus(10000)
{
setType(typeCode_);
}
void Employee::setType(int typeCode_)
{
if (type)
{
delete type;
type = nullptr;
}
// Note:
type = EmployeeType::newType(typeCode_);
}
int Employee::payAmount()
{
switch (getType() )
{
case EmployeeType::ENGINEER:
return monthlySalary;
case EmployeeType::MANAGER:
return monthlySalary + bonus;
default:
return 0;
}
}
int Employee::getType()
{
return type->getTypeCode();
}
Employee::~Employee()
{
if (type)
delete type;
}
// Engineer.cpp
#include "Engineer.h"
int Engineer::getTypeCode()
{
return EmployeeType::ENGINEER;
}
// Manager.cpp
#include "Manager.h"
int Manager::getTypeCode()
{
return EmployeeType::MANAGER;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = new Employee(EmployeeType::MANAGER);
int pay = pEmployee->payAmount();
pEmployee->setType(EmployeeType::ENGINEER);
pay = pEmployee->payAmount();
delete pEmployee;
}
3.3 重构5
处理 条件函数 payAmount(): 含条件语句(switch/if)
payAmount() 从 原宿主类(Employee) 移到 新类层次(EmployeeType)
[1] payAmount() 所属对象指针 this 作实参转调 新类层次新增的 vf: payAmount(Employee* )
[2] 条件分支的 每个分支 -> 对应的 具体子类(Engineer/Manager)
// Employee.h
#pragma once
#include "EmployeeType.h"
class Employee
{
private:
EmployeeType* type;
int monthlySalary;
int bonus;
public:
Employee(int typeCode_);
void setType(int typeCode_);
// (1) Note1: Conditional Func changed to call newClass's Additional vf type->payAmount(this)
int payAmount();
int getMonthlySalary();
int getBonus();
~Employee();
int getType(); // (5) Note5: getType() not used
};
// EmployeeType.h
#pragma once
class Employee; // (3) Note3: newClass's headerFile should forward declare original attached Class rather than include its headerFile,
// otherwise, include circularly
class EmployeeType
{
public:
static constexpr int ENGINEER = 0;
static constexpr int MANAGER = 1;
public:
static EmployeeType* newType(int typeCode);
// (2) Note2: Add vf to newClass, with para = attached Class ptr: Replace Conditional with Polymorphism
virtual int payAmount(Employee* pEmployee) = 0;
virtual int getTypeCode() = 0; // (6) Note6: getType() not used
};
// Engineer.h
#pragma once
// (4) Note4: 具体子类(Engineer.h) include(依赖)新类(EmployeeType.h) 和原宿主类(Employee.h),
// 但新类不 include(而是 前向声明)原宿主类 => include(依赖) 不构成环
#include "EmployeeType.h"
#include "Employee.h"
class Engineer: public EmployeeType
{
public:
virtual int payAmount(Employee* pEmployee);
int getTypeCode();
};
// Manager.h
#pragma once
#include "EmployeeType.h"
#include "Employee.h"
class Manager: public EmployeeType
{
public:
virtual int payAmount(Employee* pEmployee);
int getTypeCode();
};
// EmployeeTypeFactory.cpp
#include "EmployeeType.h"
#include "Engineer.h"
#include "Manager.h"
EmployeeType*
EmployeeType::newType(int typeCode_)
{
switch (typeCode_)
{
case ENGINEER:
return new Engineer();
case MANAGER:
return new Manager();
default:
return nullptr;
}
}
// Employee.cpp
#include "Employee.h"
Employee::Employee(int typeCode_)
: type(nullptr), monthlySalary(20000), bonus(10000)
{
setType(typeCode_);
}
void Employee::setType(int typeCode_)
{
if (type)
{
delete type;
type = nullptr;
}
type = EmployeeType::newType(typeCode_);
}
int Employee::payAmount()
{
return type->payAmount(this);
}
int Employee::getMonthlySalary()
{
return monthlySalary;
}
int Employee::getBonus()
{
return bonus;
}
int Employee::getType()
{
return type->getTypeCode();
}
Employee::~Employee()
{
if (type)
delete type;
}
// Engineer.cpp
#include "Engineer.h"
int Engineer::payAmount(Employee* pEmployee)
{
return pEmployee->getMonthlySalary();
}
int Engineer::getTypeCode()
{
return EmployeeType::ENGINEER;
}
// Manager.cpp
#include "Manager.h"
int Manager::payAmount(Employee* pEmployee)
{
return pEmployee->getMonthlySalary() + pEmployee->getBonus();
}
int Manager::getTypeCode()
{
return EmployeeType::MANAGER;
}
// main.cpp
#include "Employee.h"
int main()
{
Employee* pEmployee = new Employee(EmployeeType::MANAGER);
int pay = pEmployee->payAmount();
pEmployee->setType(EmployeeType::ENGINEER);
pay = pEmployee->payAmount();
delete pEmployee;
}
3.4 重构 7
: Push Down Field & Method
方法同 2.3
网友评论