参考:
[状态设计模式 (refactoringguru.cn)](https://refactoringguru.cn/design-patterns/mediator)
4. 状态模式 — Graphic Design Patterns (design-patterns.readthedocs.io)
design-patterns-cpp/State.cpp at master · JakubVojvoda/design-patterns-cpp · GitHub
文章目录
- 一、什么是状态模式?
- 二、实现
- 三、优缺点
- 优点
- 缺点
- 四、适用环境
- 五、模式应用
- 六、模式扩展
- 共享状态
一、什么是状态模式?
状态模式定义:允许一个对象在其内部状态改变时改变它的行为,使其看上去就像改变了自身所属的类一样。
二、实现
状态(State)模式包含以下主要角色:
1、上下文(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。
2、状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。
3、具体状态(Concrete State):实现抽象状态定义的接口。
/*
* C++ Design Patterns: State
* Author: Jakub Vojvoda [github.com/JakubVojvoda]
* 2016
*
* Source code is licensed under MIT License
* (for more details see LICENSE)
*
*/
#include <iostream>
/*
* State
* defines an interface for encapsulating the behavior associated
* with a particular state of the Context
*/
class State
{
public:
virtual ~State() { /* ... */ }
virtual void handle() = 0;
// ...
};
/*
* Concrete States
* each subclass implements a behavior associated with a state
* of the Context
*/
class ConcreteStateA : public State
{
public:
~ConcreteStateA() { /* ... */ }
void handle()
{
std::cout << "State A handled." << std::endl;
}
// ...
};
class ConcreteStateB : public State
{
public:
~ConcreteStateB() { /* ... */ }
void handle()
{
std::cout << "State B handled." << std::endl;
}
// ...
};
/*
* Context
* defines the interface of interest to clients
*/
class Context
{
public:
Context() : state() { /* ... */ }
~Context()
{
delete state;
}
void setState( State* const s )
{
if ( state )
{
delete state;
}
state = s;
}
void request()
{
state->handle();
}
// ...
private:
State *state;
// ...
};
int main()
{
Context *context = new Context();
context->setState( new ConcreteStateA() );
context->request();
context->setState( new ConcreteStateB() );
context->request();
delete context;
return 0;
}
三、优缺点
优点
- 封装了转换规则。
- 开闭原则。 无需修改已有状态类和上下文就能引入新状态。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
缺点
- 如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
四、适用环境
- 对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。
- 代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。在这些条件语句中包含了对象的行为,而且这些条件对应于对象的各种状态。
五、模式应用
状态模式在工作流或游戏等类型的软件中得以广泛使用,甚至可以用于这些系统的核心功能设计,如在政府OA办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态,而且批文状态不同时对批文的操作也有所差异。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。
六、模式扩展
共享状态
-
在有些情况下多个环境对象需要共享同一个状态,如果希望在系统中实现多个环境对象实例共享一个或多个状态对象,那么需要将这些状态对象定义为环境的静态成员对象。
-
简单状态模式与可切换状态的状态模式
- 简单状态模式:简单状态模式是指状态都相互独立,状态之间无须进行转换的状态模式,这是最简单的一种状态模式。对于这种状态模式,每个状态类都封装与状态相关的操作,而无须关心状态的切换,可以在客户端直接实例化状态类,然后将状态对象设置到环境类中。如果是这种简单的状态模式,它遵循“开闭原则”,在客户端可以针对抽象状态类进行编程,而将具体状态类写到配置文件中,同时增加新的状态类对原有系统也不造成任何影响。
- 可切换状态的状态模式:大多数的状态模式都是可以切换状态的状态模式,在实现状态切换时,在具体状态类内部需要调用环境类Context的setState()方法进行状态的转换操作,在具体状态类中可以调用到环境类的方法,因此状态类与环境类之间通常还存在关联关系或者依赖关系。通过在状态类中引用环境类的对象来回调环境类的setState()方法实现状态的切换。在这种可以切换状态的状态模式中,增加新的状态类可能需要修改其他某些状态类甚至环境类的源代码,否则系统无法切换到新增状态。