首页 > 代码库 > 状态模式

状态模式

状态模式

1. 概述

  状态模式,就是将对象的状态和对应状态下的行为分离开来,不再是简单的if…else或switch…case分支结构了,而是每一个状态都对应一个类,一个类集中管理一个状态;在多状态的情况下,简化了程序的维护和管理,让程序结构简明化,同时也易于扩展。

2. 解决的问题

  当控制一个对象状态转换的条件表达式过于复杂时的情况。

3. 模式中的角色

  1) 上下文环境(Context):定义了客户程序所需接口并维护一个具体状态角色实例,将与状态相关的操作委托给当前的ConcreteState对象处理。

  2) 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

  3) 具体状态(Concrete State):实现抽象状态定义的接口。

4. 优点

  1) 状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。

  2) 所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。

  3) 状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

5. 缺点

  1) 导致较多的ConcreteState子类

6. 适用场景

  下面是GOF在《设计模式》中给出的状态模式的适用情况:

  1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

  2) 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

7. 与策略模式的比较

  下面是策略模式和方法模式的UML图

      技术分享                         

  二者外表一样,只是二者的关注点不一样:

  1) 策略模式关注行为的变化,但归根结底只有一个行为,变化的只是行为的实现。客户不关注这些.当新增变化时对客户可以没有任何影响。

  2) 状态模式同样关注行为的变化,但这个变化是由状态来驱动,一般来说每个状态和行为都不同。客户需要关注新增的状态或行为与已有的不同。

  状态模式一个形象的比喻是”饱了睡,饿了吃”.在这里”饱和饿”是两种状态,”睡和吃”是两种行为.

 

8.代码实现

1)用if...else的情况

 1 typedef enum tagState 2 { 3     state, 4     state1, 5     state2 6 }State; 7  8 void Action(State actionState) 9 {10     if (actionState == state)11     {12          // DoSomething13     }14     else if (actionState == state1)15     {16          // DoSomething17     }18     else if (actionState == state2)19     {20          // DoSomething21     }22     else23     {24          // DoSomething25     }26 }

2)用状态模式表现--分离状态和行为

 1 #include <iostream> 2 using namespace std; 3  4 class Context; 5 class State 6 { 7 public: 8     virtual void Handle(Context *pContext) = 0; 9 };10 11 class ConcreteStateA : public State12 {13 public:14     virtual void Handle(Context *pContext)15     {16          cout<<"I am concretestateA."<<endl;17     }18 };19 class ConcreteStateB : public State20 {21 public:22     virtual void Handle(Context *pContext)23     {24          cout<<"I am concretestateB."<<endl;25     }26 };27 28 class Context29 {30 public:31     Context(State *pState) : m_pState(pState){}32     void Request()33     {34          if (m_pState)35          {36               m_pState->Handle(this);37          }38     }39      void ChangeState(State *pState)40     {41          m_pState = pState;42     }43 private:44     State *m_pState;45 };46 47 int main()48 {49     State *pStateA = new ConcreteStateA();50     State *pStateB = new ConcreteStateB();51     Context *pContext = new Context(pStateA);52 53     pContext->Request();54     pContext->ChangeState(pStateB);55     pContext->Request();56 57     delete pContext;58     delete pStateB;59     delete pStateA;60 }

3)状态模式--旋转开关

  "一般的状态判断"如:

    if (which==1) state="hello";     

    else if (which==2) state="hi";     

    else if (which==3) state="bye";

  如果改成:

    if (state.euqals("bye")) state="hello";     

    else if (state.euqals("hello")) state="hi";     

    else if (state.euqals("hi")) state="bye";

  这就是 "开关切换状态",是将state的状态从"hello"切换到"hi",再切换到""bye";在切换到"hello",好象一个旋转开关,这种状态改变就可以使用State模式了.

.h文件:

 1 class Context; 2 class State 3 { 4 public: 5     virtual void Handle(Context* pContext)=0; 6 }; 7  8 class ConcreteStateA : public State 9 {10 public:11     virtual void Handle(Context* pContext);12 };13 14 class ConcreteStateB : public State15 {16 public:17     virtual void Handle(Context* pContext);18 };19 20 class ConcreteStateC : public State21 {22 public:23     virtual void Handle(Context* pContext);24 };25 26 class Context27 {28 public:29     Context(State* pState): m_pState(pState){}30     void Request()31     {32         if(m_pState)33     {34         m_pState->Handle(this);35     }36     }37     void ChangeState(State* pState)38     {39         m_pState = pState;40     }41 42 private:43     State* m_pState;44 };

.cpp文件

 1 //执行该状态的行为并改变状态 2 void ConcreteStateA::Handle(Context* pContext) 3 { 4     cout << "ConcreteStateA" << endl; 5     pContext->ChangeState(new ConcreteStateB()); 6 } 7  8 //执行该状态的行为并改变状态 9 void ConcreteStateB::Handle(Context* pContext)10 {11     cout << "ConcreteStateB" << endl;12     pContext->ChangeState(new ConcreteStateC());13 }14 15 //执行该状态的行为并改变状态16 void ConcreteStateC::Handle(Context* pContext)17 {18     cout << "ConcreteStateC" << endl;19     pContext->ChangeState(new ConcreteStateA());20 }

客户端:

 1 #include "State.h" 2  3 int main() 4 { 5     State* pState = new ConcreteStateA(); 6     Context* pContext = new Context(pState); 7     pContext->Request(); 8     pContext->Request(); 9     pContext->Request();10     pContext->Request();11     pContext->Request();12     return 0;13 }

 

状态模式