一. 状态模式

状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

应用场景:

  1. 如果对象需要根据自己当前状态进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可使用状态模式
  2. 如果某个类需要根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时,可使用该模式
  3. 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式

我们来模拟一个例子:水在不同温度下,表现出不同的状态,固态、液态和气态

#include <cstdio>                                                                                                                                       
#include <memory>

class State{
public:
    virtual ~State() = default;

public:
    virtual void showState(void) = 0;
};

class Gas : public State{
public:
    void showState(void) override{
        printf("Gas\n");
    }
};

class Solid : public State{
public:
    void showState(void) override{
        printf("Solid\n");
    }
};

class Liquid : public State{
public:
    void showState(void) override{
        printf("Liquid\n");
    }
};

class Water{
private:
    std::unique_ptr<State> state;
    int temperature;

public:
    Water()
    :state(std::make_unique<Liquid>()), temperature(25){}

public:
    void showState(void){
        printf("%d degree Celsius, ", this->temperature);
        this->state->showState();
    }

    void setTemperature(int temperature){
        this->temperature = temperature;
        if(temperature <= 0)
            this->state = std::make_unique<Solid>();
        else if(temperature <= 100)
            this->state = std::make_unique<Liquid>();
        else
            this->state = std::make_unique<Gas>();
    }
};

int main(void){
    Water water;
    water.showState();
    
    water.setTemperature(0);
    water.showState();
    
    water.setTemperature(101);
    water.showState();
    return 0;
}

状态模式与状态机的概念紧密相关。状态模式与策略模式相似,但他们有一个关键性的不同:在状态模式中,特定状态知道其它所有状态的存在,且能触发从一个状态到另一个状态的转换;策略模式则完全不知道其它策略的存在

二. 适配器模式

适配器模式:将一个类的接口转换成客户希望的另一个接口,使得原本接口不兼容而不能一起工作的那些类可以一起工作

应用场景:当你希望使用某个类,但是其接口与其它代码不兼容时,可以使用适配器模式

我们来模拟一个例子:中国插排和英国插排并不相同,但通过转接器就可以使用英国插排为依赖中国插排的电器充电

#include <cstdio>                                                                                                                                       
#include <string>

class Socket{
private:
    int pin_num;
    std::string pin_shape;

public:
    Socket(int pin_num, const std::string &pin_shape)
    :pin_num(pin_num), pin_shape(pin_shape){}

    virtual ~Socket() = default;

public:
    int getPinNum(void) const{
        return this->pin_num;
    }

    std::string getPinShape(void) const{
        return this->pin_shape;
    }
};

class BritishSocket : public Socket{
public:
    BritishSocket()
    :Socket(3, "T-shaped square"){}
};                                                                                                                                             

class Adapt{
public:
    Socket adapt(const BritishSocket &british_socket){
        return Socket(3, "Figure-eight flat");
    }
};

class Computer{
public:
    void Charging(const Socket &socket){
        if(socket.getPinNum() == 3 && socket.getPinShape() == "Figure-eight flat")
            printf("Charging successful.\n");
        else
            printf("The socket doesn't match.\n");
    }
};

int main(void){
    BritishSocket british_socket;
    Computer my_computer;
    my_computer.Charging(british_socket);

    Adapt apt;
    my_computer.Charging(apt.adapt(british_socket));
    return 0;
}

作业

对于 x 的某个给定值,求出一个多项式在 x 的值,也可以形式化为一种累积。假定需要求下面多项式的值: $$a_n x^n+a_{n-1}x^{n-1}+\dots+a_1 x+a_0$$ 采用著名的 Horner 规则,可以构造出下面的计算:$$(\dots(a_n x+a_{n-1}) x+\dots+a_1) x+a_0$$ 利用 Horner 规则求多项式的值,假定多项式的系数安排在一个 vector 里