状态模式(State)

参考:

[状态设计模式 (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办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态,而且批文状态不同时对批文的操作也有所差异。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。

六、模式扩展

共享状态

  • 在有些情况下多个环境对象需要共享同一个状态,如果希望在系统中实现多个环境对象实例共享一个或多个状态对象,那么需要将这些状态对象定义为环境的静态成员对象。

  • 简单状态模式与可切换状态的状态模式

    1. 简单状态模式:简单状态模式是指状态都相互独立,状态之间无须进行转换的状态模式,这是最简单的一种状态模式。对于这种状态模式,每个状态类都封装与状态相关的操作,而无须关心状态的切换,可以在客户端直接实例化状态类,然后将状态对象设置到环境类中。如果是这种简单的状态模式,它遵循“开闭原则”,在客户端可以针对抽象状态类进行编程,而将具体状态类写到配置文件中,同时增加新的状态类对原有系统也不造成任何影响。
    2. 可切换状态的状态模式:大多数的状态模式都是可以切换状态的状态模式,在实现状态切换时,在具体状态类内部需要调用环境类Context的setState()方法进行状态的转换操作,在具体状态类中可以调用到环境类的方法,因此状态类与环境类之间通常还存在关联关系或者依赖关系。通过在状态类中引用环境类的对象来回调环境类的setState()方法实现状态的切换。在这种可以切换状态的状态模式中,增加新的状态类可能需要修改其他某些状态类甚至环境类的源代码,否则系统无法切换到新增状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值