C++设计模式——状态模式

栏目: C++ · 发布时间: 6年前

内容简介:前言在实际开发中,我们经常会遇到这种情况;一个对象有多种状态,在每一个状态下,都会有不同的行为。那么在代码中我们经常是这样实现的。而这种就好比

前言

在实际开发中,我们经常会遇到这种情况;一个对象有多种状态,在每一个状态下,都会有不同的行为。那么在代码中我们经常是这样实现的。

typedef enum tagState
{
     state,
     state1,
     state2
}State;

void Action(State actionState)
{
     if (actionState == state)
     {
          // DoSomething
     }
     else if (actionState == state1)
     {
          // DoSomething
     }
     else if (actionState == state2)
     {
          // DoSomething
     }
     else
     {
          // DoSomething
     }
}

而这种就好比 简单工厂模式 ,当我们增加新的状态类型时,我们又需要修改原来的代码,这种对于测试是很不利的;由于简单工厂的缺点那么的明显,后来的工厂模式就克服了这个缺点,我们就可以借鉴工程模式,来解决这种随着状态增加而出现的多分支结构,而这就是我今天要总结的状态模式。

?

状态模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。状态模式的重点在于状态转换,很多时候,对于一个对象的状态,我们都是让这个对象包含一个状态的属性,这个状态属性记录着对象的具体状态,根据状态的不同使用分支结构来执行不同的功能,就像上面的代码那样处理;就像上面说的,类中存在大量的结构类似的分支语句,变得难以维护和理解。状态模式消除了分支语句,就像 工厂模式 消除了简单工厂模式的分支语句一样,将状态处理分散到各个状态子类中去,每个子类集中处理一种状态,这样就使得状态的处理和转换清晰明确。

?

UML类图

C++设计模式——状态模式

Context:定义客户端感兴趣的接口,并且维护一个ConcreteState子类的实例,这个实例定义当前状态;

State:定义一个接口以封装与Context的一个特定状态相关的行为;

ConcreteState subclasses:每一个子类实现一个与Context的一个状态相关的行为。

它们之间的协作步骤如下:

    1. Context将与状态相关的请求委托给当前的ConcreteState对象处理;
    2. Context可以将自身作为一个参数传递给处理该请求的状态对象。这使得状态对象在必要时可以访问Context;
    3. Context是客户使用的主要接口。客户可用状态对象来配置一个Context,一旦一个Context配置完毕,它的客户不再需要直接与状态对象打交道;

?

使用场合

在以下两种情况下均可使用State模式:

  1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为;
  2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其它对象而独立变化。

?

代码实现

#include <iostream>
using namespace std;

class Context;

class State
{
public:
     virtual void Handle(Context *pContext) = 0;
};

class ConcreteStateA : public State
{
public:
     virtual void Handle(Context *pContext)
     {
          cout<<"I am concretestateA."<<endl;
     }
};

class ConcreteStateB : public State
{
public:
     virtual void Handle(Context *pContext)
     {
          cout<<"I am concretestateB."<<endl;
     }
};

class Context
{
public:
     Context(State *pState) : m_pState(pState){}

     void Request()
     {
          if (m_pState)
          {
               m_pState->Handle(this);
          }
     }

     void ChangeState(State *pState)
     {
          m_pState = pState;
     }

private:
     State *m_pState;
};

int main()
{
     State *pStateA = new ConcreteStateA();
     State *pStateB = new ConcreteStateB();
     Context *pContext = new Context(pStateA);
     pContext->Request();

     pContext->ChangeState(pStateB);
     pContext->Request();

     delete pContext;
     delete pStateB;
     delete pStateA;
}

总结

状态模式总的来说是非常好理解的;没有多么深奥的时序关系,就是简单的将对象的状态和对应状态下的行为分离开来,不再是简单的if…else或switch…case分支结构了,而是每一个状态都对应一个类,一个类集中管理一个状态;在多状态的情况下,简化了程序的维护和管理,让程序结构简明化,同时也易于扩展。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复盘

复盘

陈中 / 机械工业出版社 / 2013-7-23 / 29

复盘是围棋中的一种学习方法,指的是在写完一盘棋之后,要重新摆一遍,看看哪里下得好,哪里下得不好,对下得好和不好的,都要进行分析和推演。 柳传志第一个将复盘引入到做事之中,成为联想三大方法论之一,在联想每一个重大决策的背后,都有复盘的身影。 本书完整系统讲述了复盘的内容,清晰了复盘的价值,给出了复盘的操作步骤,我们可以在自己的工作生活中,应用复盘的方法,向自己学习,随时随地的提高自己,把......一起来看看 《复盘》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具