《重构:改善既有代码的设计》 重新组织数据 之 15

版权声明:请注明转发出处 https://blog.csdn.net/mafucun1988/article/details/89741611

《重构:改善既有代码的设计》中提到过很多重构方法,关于重新组织数据的方法有16种。本文介绍:
以state/strategy取代类型码 replace type code with state/strategy

  • 名称:以state/strategy取代类型码 replace type code with state/strategy
  • 概要:有一个类型码,会影响类的行为,但你无法通过继承手法消除它。以状态对象取代类型码
  • 动机:本重构和replace type code wih subclasses很相似,但如果“类型码的值在对象声明期中发生变化”或“其他原因使得宿主类不能被继承”,就可以使用本重构。

  • 做法:
    • 使用self encapsulate field将类型码自我封装起来
    • 新建一个类,根据类型码的用途为它命名。这就是一个状态对象
    • 为这个新类添加子类,每个子类对应一种类型码
    • 在超类中建立一个抽象的查询函数,用以返回类型码。在每个子类中覆写该函数,返回确切的类型码
    • 编译
    • 在源类中建立一个字段,用以保存新建的状态对象
    • 调整源类中负责查询类型码的函数,将查询动作转发给状态对象
    • 调整源类中为类型码设值的函数,将一个恰当的状态对象子类赋值给“保存状态对象”的那个字段
    • 编译,测试
  • 代码演示

修改之前的代码: 

/////////////////////////.h
lass Employee
{
public:
    Employee(int code);
        static const int ENGINEER;
        static const int SALESMAN;
        static const int MANAGER;
        double payAmount();
private:
    int m_code;
    double m_monthlySalary;
    double m_commission;
    double m_bonus;
};

//////////////////////////.cpp
const int Employee::ENGINEER = 0;
const int Employee::SALESMAN = 1;
const int Employee::MANAGER = 2;
Employee::Employee(int code)
{
    m_code = code;
}

double Employee::payAmount()
{
    switch (m_code) {
    case  ENGINEER:
        return m_monthlySalary;
    case SALESMAN:
        return m_monthlySalary + m_commission;
    case MANAGER:
        return  m_monthlySalary + m_bonus;
    default:
        return 0;

    }
}
//////////////////////////main.cpp
Employee engineer(Employee::ENGINEER);
qDebug() << "employee code = " <<engineer.getCode();
qDebug() << "employee payamount = " <<engineer->payAmount();

1) 因为将来工程师会升级为经理,所以对象的类型码是可变的,所以不能使用继承方式来处理类型码
2)使用self encapsulate field将类型码自我封装起来
3)需要声明一个状态类,把它声明为一个抽象类,并提供一个抽象函数来返回类型码
4)修改类型码访问函数,把子类和employee类联系起来
5)将所有关于类型码和子类的知识都移到新类
修改之后的代码:

/////////////////////////.h
class EmployeeType;
class Employee
{
public:
    Employee(EmployeeType* code);

    double payAmount();
    int getCode() const;
    void setCode(int code);

private:
    //int m_code;
    EmployeeType* m_code;
    double m_monthlySalary;
    double m_commission;
    double m_bonus;
};

class EmployeeType
{
public:
    static const int ENGINEER;
    static const int SALESMAN;
    static const int MANAGER;
    static EmployeeType* newType(int code);
    virtual int getTypeCode() = 0;
};

class Engineer : public EmployeeType
{
public:
    int getTypeCode();
};

class Salesman : public EmployeeType
{
public:
    int getTypeCode();
};

class Manager : public EmployeeType
{
public:
    int getTypeCode();
};

class Error : public EmployeeType
{
public:
    int getTypeCode();
};
//////////////////////////.cpp

const int EmployeeType::ENGINEER = 0;
const int EmployeeType::SALESMAN = 1;
const int EmployeeType::MANAGER = 2;
Employee::Employee(EmployeeType* code):
    m_monthlySalary(100),
    m_commission(10),
    m_bonus(200)
{
    m_code = code;
}

double Employee::payAmount()
{
    switch (getCode()) {
    case  EmployeeType::ENGINEER:
        return m_monthlySalary;
    case EmployeeType::SALESMAN:
        return m_monthlySalary + m_commission;
    case EmployeeType::MANAGER:
        return  m_monthlySalary + m_bonus;
    default:
        return 0;

    }
}

int Employee::getCode() const
{
    return m_code->getTypeCode();
}

void Employee::setCode(int code)
{
   m_code = m_code->newType(code);
}

int Engineer::getTypeCode()
{
    return ENGINEER;
}


int Salesman::getTypeCode()
{
    return SALESMAN;
}

int Manager::getTypeCode()
{
    return MANAGER;
}

int Error::getTypeCode()
{
    return MANAGER;
}

EmployeeType* EmployeeType::newType(int code)
{
    switch (code) {
    case  ENGINEER:
        return new Engineer();
    case SALESMAN:
        return new Salesman();
    case MANAGER:
        return new Manager();
    default:
        return nullptr;
    }
}
////////////////////////main.cpp
EmployeeType* engineer_type =  new Engineer();
    EmployeeType* manager_type =  new Manager();
    Employee *engineer = new Employee(engineer_type);
    qDebug() << "employee code = " <<engineer->getCode();
    qDebug() << "employee payamount = " <<engineer->payAmount();
    engineer->setCode(Manager().getTypeCode());
    qDebug() << "employee code = " <<engineer->getCode();
    qDebug() << "employee payamount = " <<engineer->payAmount();

猜你喜欢

转载自blog.csdn.net/mafucun1988/article/details/89741611