设计模式之状态模式(State )

状态模式是根据其状态变化来改变对象的行为,允许对象根据内部状态来实现不同的行为。内容类可以具有大量的内部状态,每当调用实现时,就委托给状态类进行处理。

作用

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

类视图

设计模式之状态模式(State )

实现

class State;
class LowState; //低等折扣
class MediaState; //中等折扣
class HighState;  //高等折扣
//折扣
class Discount
{
public:
    Discount(State* sta):m_state(sta){}
    ~Discount(){delete State;}
    void request(){ m_state->handle(this);}
    void setstate(State* sta)
    {
        delete m_state;
        m_state = sta;
    }
    int GetBuyNum(){return m_nBuyNum;}
    void SetBuyNum(int nNum){m_nBuyNum =nNum; }
private:
    State* m_state;
    int m_nBuyNum;
};

//运行系统
class State
{
public:
    virtual void handle(Discount*)=0;
};

class LowState : public State
{
public:
     LowState();
    ~ LowState();
    void handle(Discount* pDis)
    {
        if (pDis)
        {
            int nNum = pDis->GetBuyNum();
            if (nNum<=10)
            {
                cout<< "打9折";
            }
            else
            {
                pDis->setstate(new MediaState());
                pDis->request();
            }
        }
    }  
};

class MediaState : public State
{
public:
     MediaState();
    ~ MediaState();
    void handle(Discount* pDis)
    {
        if (pDis)
        {
            int nNum = pDis->GetBuyNum();
            if(nNum<=10)
            {
                pDis->setstate(new LowState());
                pDis->getstate();               
            }
            else if (nNum>10 && nNum <=50)
            {
                cout<< "打7折";
            }
            else
            {
                pDis->setstate(new HighState());
                pDis->request();
            }
        }
    } 
    
};


class HighState : public State
{
public:
    void handle(Discount* pDis)
    {
        if (pDis)
        {
            int nNum = pDis->GetBuyNum();
            if (nNum>50)
            {
                cout<< "打5折";
            }
            else
            {
                pDis->setstate(new MediaState());
                pDis->request();
            }
        }
    }
};

int main()
{

    Discount disc(new LowState());
    disc.SetBuyNum(40);
    disc.request();

}

状态模式里可以看到策略模式和责任链模式的影子,从结构和功能上会有些相似;

策略模式和状态模式最为相像,其二者主要区别是策略模式更关心的是strategy的类型多态实现,一般会在外部调用时进行指明;而状态模式不会直接决定State的具体实现,而是通过内部状态参数来决定。

责任链模式由前后的链条关系,在创建时需要明确指出,而状态模式是由状态选择其多态的实现。
所以状态模式之所以单独独立出来,就是为了凸显在不同状态下的不同实现

这篇电梯的实现很形象,大家可以参考电梯应用

应用场景

  1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  2. 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。