标签:
状态模式
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