C++状态模式
2017-11-27 18:03
169 查看
简述
状态模式(State Pattern)是行为设计模式之一。当对象根据其内部状态改变其行为时,将使用状态设计模式。简述
模式结构
优缺点
适用场景
案例分析
代码实现
版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820
模式结构
UML 结构图:Context(上下文):定义一个与 Client 交互的接口。它维护对 ConcreteState 对象的引用,可以用该对象来定义当前状态。
State(抽象状态):定义接口,来声明每个 ConcreteState 应该做什么。
ConcreteState(具体状态):为 State 中定义的方法提供实现。
优缺点
优点:实现多态行为的好处是显而易见的,并且很容易添加状态来支持额外的行为。
在状态模式中,对象的行为是其状态中函数的结果,并且在运行时根据状态改变行为,这就消除了对
switch/case或
if/else条件逻辑的依赖。
可以提高内聚性,因为状态特定的行为被聚合到具体的类中,这些类被放在代码中的一个位置。
缺点:
使用状态模式,必然会增加系统中类和对象的个数。
由于状态模式的结构与实现较为复杂,一旦使用不当,将会导致程序结构和代码的混乱。
若要添加新的状态,则需要修改负责转换的源代码,否则无法转换到新增的状态,而且修改某个状态的行为也要修改源代码。
适用场景
一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。
案例分析
交通信号灯 - 文明出行,从我做起。红灯停,绿灯行,黄灯亮了等一等。
交叉路口红绿灯,指挥交通显神通;
绿灯亮了放心走,红灯亮了别抢行;
黄灯亮了要注意,人人遵守红绿灯。
可以看到,交通信号灯的状态流:红灯 -> 绿灯 -> 黄灯。。。实际上,就是各个状态之间的相互切换,这完全符合状态模式。
代码实现
创建上下文上下文由 TrafficLights 表示,该类有一个 IState 变量,在构造中被初始化为 RedLight(红灯):
// context.h #ifndef CONTEXT_H #define CONTEXT_H #include "concrete_state.h" // 交通信号灯 class TrafficLights { public: TrafficLights() { m_pState = new RedLight(this); } void SetState(IState* state) { m_pState = state; } void Request() { m_pState->Handle(); } private: IState* m_pState; }; #endif // CONTEXT_H
注意: 在上下文提供的方法中,实际上使用的是 IState 的相应方法。
创建抽象状态
IState 有一个
Handle()接口,用于改变状态:
// state.h #ifndef STATE_H #define STATE_H // 信号灯的状态 class IState { public: virtual void Handle() = 0; }; #endif // STATE_H
创建具体状态
具体的状态有三个 - 红灯、绿灯、黄灯:
// concrete_state.h #ifndef CONCRETE_STATE_H #define CONCRETE_STATE_H #include "state.h" class TrafficLights; // 红灯 class RedLight : public IState { public: RedLight(TrafficLights* context); virtual void Handle() override; private: TrafficLights* m_pContext; }; // 绿灯 class GreenLight : public IState { public: GreenLight(TrafficLights* context); virtual void Handle() override; private: TrafficLights* m_pContext; }; // 黄灯 class YellowLight : public IState { public: YellowLight(TrafficLights* context); virtual void Handle() override; private: TrafficLights* m_pContext; }; #endif // CONCRETE_STATE_H
它们所提供的方法有对上下文对象的引用,并且能够改变它的状态:
// concrete_state.cpp #include "concrete_state.h" #include "context.h" #include <iostream> // 红灯 RedLight::RedLight(TrafficLights* context) : m_pContext(context) {} void RedLight::Handle() { std::cout << "Red Light" << std::endl; m_pContext->SetState(new GreenLight(m_pContext)); delete this; } // 绿灯 GreenLight::GreenLight(TrafficLights* context) : m_pContext(context) {} void GreenLight::Handle() { std::cout << "Green Light" << std::endl; m_pContext->SetState(new YellowLight(m_pContext)); delete this; } // 黄灯 YellowLight::YellowLight(TrafficLights* context) : m_pContext(context) {} void YellowLight::Handle() { std::cout << "Yellow Light" << std::endl; m_pContext->SetState(new RedLight(m_pContext)); delete this; }
创建客户端
Ready,go!“交通警察”开始工作啦:
// main.cpp #include "context.h" #include <iostream> #include <windows.h> int main() { TrafficLights tl; enum TLState {Red, Green, Yellow}; TLState state = Red; // 初始状态为红灯 int i = 0; // 总次数 int seconds; // 秒数 while (true) { // 表示一个完整的状态流(红灯->绿灯->黄灯)已经完成 if (i % 3 == 0) std::cout << "**********" << "Session " << ((i+1)/3)+1 << "**********" << std::endl; // 根据当前状态来设置持续时间,红灯(6秒)、绿灯(4秒)、黄灯(2秒) if (state == Red) { seconds = 6; state = Green; } else if (state == Green) { seconds = 4; state = Yellow; } else if (state == Yellow) { seconds = 2; state = Red; } // 休眠 Sleep(seconds * 1000); tl.Request(); i++; } return 0; }
输出如下:
[b]*****Session 1*****[/b]
Red Light
Green Light
Yellow Light
[b]*****Session 2*****[/b]
Red Light
Green Light
Yellow Light
[b]*****Session 3*****[/b]
Red Light
Green Light
Yellow Light
[b]*****Session n*****[/b]
…
交通信号灯的状态一般会持续一定时间,这里使用
Sleep()休眠的方式来实现。当然,现实生活中信号灯的各个状态持续时间较长,为了更快地在各个状态之间进行切换,我们设置了短时间的间隔 - 红灯(6秒)、绿灯(4秒)、黄灯(2秒)。
相关文章推荐
- 使用状态模式解决简单的信号转换问题
- 命令模式、状态模式、责任链模式区别(转)
- 23状态模式
- 设计模式——状态模式
- 谈谈下订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)
- Android状态栏微技巧,带你真正理解沉浸式模式
- 《Head First 设计模式》之状态模式
- 设计模式 状态模式 以自动售货机为例
- java设计模式-状态模式(STATE)
- 状态模式
- Singleton单一状态模式(单例模式)
- 状态模式
- 设计模式整理_状态模式
- 状态栏的设置和沉浸式模式的理解
- 23种设计模式之状态模式
- 设计模式之状态模式
- 状态模式
- 状态模式
- 简明 状态模式
- 深入理解JavaScript系列(43):设计模式之状态模式