码迷,mamicode.com
首页 > 其他好文 > 详细

状态模式

时间:2015-01-26 11:49:19      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:

状态模式

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          // DoSomething
13     }
14     else if (actionState == state1)
15     {
16          // DoSomething
17     }
18     else if (actionState == state2)
19     {
20          // DoSomething
21     }
22     else
23     {
24          // DoSomething
25     }
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 State
12 {
13 public:
14     virtual void Handle(Context *pContext)
15     {
16          cout<<"I am concretestateA."<<endl;
17     }
18 };
19 class ConcreteStateB : public State
20 {
21 public:
22     virtual void Handle(Context *pContext)
23     {
24          cout<<"I am concretestateB."<<endl;
25     }
26 };
27 
28 class Context
29 {
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 State
15 {
16 public:
17     virtual void Handle(Context* pContext);
18 };
19 
20 class ConcreteStateC : public State
21 {
22 public:
23     virtual void Handle(Context* pContext);
24 };
25 
26 class Context
27 {
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 }

 

状态模式

标签:

原文地址:http://www.cnblogs.com/SnailProgramer/p/4249794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!