23种设计模式之十五(行为模式)State模式

一、简介

        State状态模式为了解决的问题是:每个事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State)。有限状态自动机(FSM)就是一个典型根据状态的不同,对输入作不同的响应(状态转移)。通常实现这类系统会使用到很多的 Switch/Case 语句,Case 某种状态,发生什么动作;Case 另外一种状态,则发生另外一种状态。但存在的问题是:(1)当状态数目不是很多的时候,witch/Case 可能可以搞定,但是当状态数目很多的时候(实际系统中也正是如此)维护一大组的 Switch/Case 语句将是一件异常困难并且容易出错的事情。(2)状态逻辑和动作实现没有分离,在很多的系统实现中,动作的实现代码直接写在状态的逻辑当中,这带来的后果就是系统的扩展性和维护得不到保证。State 模式就是被用来解决上面的问题的。
        在State模式中,将状态逻辑和动作实现进行分离。当一个操作中要维护大量的 case 分支语句,并且这些分支依赖于对象的状态。State 模式将每一个分支都封装到独立的类中。

        State 模式典型的结构图为:

        State 模式在实现中有两个关键点:(1)将State声明为Context的友元类(friend class),其作用是让State类访问Context的 protected接口ChangeSate()。(2)State及其子类中的操作都将Context*传入作为参数,主要目的是State类可以通过这个指针调用 Context 中的方法(在本示例代码中没有体现),这也是 State 模式和 Strategy模式的最大区别所在。

二、详解

1、代码实现

(1)代码state.h:

#ifndef _STATE_H_
#define _STATE_H_

class Context;
class State
{
	  public:
	  	  State();
	  	  virtual ~State();
	  	  virtual void OperationInterface(Context *) = 0;
	  	  virtual void OperationChangeState(Context *) = 0;
	  protected:
	  	  bool ChangeState(Context *con, State *st);
	  private:
};

class ConcreteStateA : public State
{
	  public:
	  	  ConcreteStateA();
	  	  virtual ~ConcreteStateA();
	  	  virtual void OperationInterface(Context *);
	  	  virtual void OperationChangeState(Context *);
	  protected:
	  private:
};

class ConcreteStateB : public State
{
	  public:
	  	  ConcreteStateB();
	  	  virtual ~ConcreteStateB();
	  	  virtual void OperationInterface(Context *);
	  	  virtual void OperationChangeState(Context *);
	  protected:
	  private:
};

#endif
(2)代码state.cpp:

#include <iostream>
#include "state.h"
#include "context.h"
using namespace std;

State::State()
{
}

State::~State()
{
}

void State::OperationInterface(Context *con)
{
	  cout<<"State::OperationInterface..."<<endl;
}

void State::OperationChangeState(Context *con)
{
}

bool State::ChangeState(Context *con, State *st)
{
	  cout<<"State::ChangeState"<<endl;
	  con->ChangeState(st);              //State类是Context类的友元类
    return true;
}

ConcreteStateA::ConcreteStateA()
{
}

ConcreteStateA::~ConcreteStateA()
{
}

void ConcreteStateA::OperationInterface(Context *con)
{
	  cout<<"ConcreteStateA::OperationInterface..."<<endl;
}
//执行该状态的行为并改变状态
void ConcreteStateA::OperationChangeState(Context *con)
{
		cout<<"+++ConcreteStateA::OperationChangeState..."<<endl;
    OperationInterface(con);
    this->ChangeState(con, new ConcreteStateB());
}

ConcreteStateB::ConcreteStateB()
{
}

ConcreteStateB::~ConcreteStateB()
{
}

void ConcreteStateB::OperationInterface(Context *con)
{
	  cout<<"ConcreteStateB::OperationInterface..."<<endl;
}
//执行该状态的行为并改变状态
void ConcreteStateB::OperationChangeState(Context *con)
{
		cout<<"+++ConcreteStateB::OperationChangeState..."<<endl;
    OperationInterface(con);
    this->ChangeState(con, new ConcreteStateA());
}
(3)代码context.h:

#ifndef _CONTEXT_H_
#define _CONTEXT_H_

class State;
class Context
{
	  public:
	  	  Context();
	  	  Context(State *state);
	  	  ~Context();
	  	  void OperationInterface();
	  	  void OperationChangeState();
	  protected:
	  private:
	  	  bool ChangeState(State *state);
	  	  friend class State;        //表明在State类中可以访问Context类的private字段
        State *_state;
};

#endif
(4)代码context.cpp:
#include <iostream>
#include "context.h"
#include "state.h"
using namespace std;

Context::Context()
{
	  _state = NULL;
}

Context::Context(State *state)
{
	  this->_state = state;
}

Context::~Context()
{
	  if (_state) delete _state;
}

void Context::OperationInterface()
{
	  _state->OperationInterface(this);
}

bool Context::ChangeState(State *state)
{
	  cout<<"Context::ChangeState"<<endl;
	  if (_state) {
	  	cout<<"...delete origin State"<<endl;
	    delete _state;
	    _state = NULL;
	  }
	  this->_state = state;
	  return true;
}
//对请求做处理,并设置下一状态
void Context::OperationChangeState()
{
	  _state->OperationChangeState(this);
}
(5)代码main.cpp:
#include <iostream>
#include "context.h"
#include "state.h"
using namespace std;

int main()
{
	  State *st = new ConcreteStateA();
	  Context *con = new Context(st);
	  
	  cout<<"origin---";
	  con->OperationInterface();
	  con->OperationChangeState();
	  cout<<"final---";
	  con->OperationInterface();
	  cout<<"---------------------"<<endl;
	  
	  con->OperationChangeState();
	  cout<<"final---";
	  con->OperationInterface();
	  
	  if (con) delete con;
	  if (st) st = NULL;
 	  return 0;
}
(6)makefile:
CFLAGS = -g
DEFINED = #-D _VERSION
LIBS = 
CC = g++
INCLUDES = -I./
OBJS= main.o context.o state.o
TARGET= main
all:$(TARGET)

$(TARGET):$(OBJS)
	$(CC) $(CFLAGS) -o $@ $(OBJS)

.SUFFIXES:.o .h
.SUFFIXES:.cpp .o
.cpp.o:
	$(CC) $(DEFINED) -c $(CFLAGS) -o $@ $<

ok:
	./$(TARGET)
clean:
	rm -f $(OBJS) $(TARGET) core *.log

2、运行结果

(Centos6.3系统中运行结果:)


     运行了代码后,先输出当前状态,然后调用Context的OperationChangeState改变状态,输出新的状态;接着转换状态,随着 Context 的状态的转变而获得了不同的结果,状态由A-B-A。

三、总结

(1)State模式和Strategy模式又很大程度上的相似:它们都有一个 Context 类,都是通过委托(组合)给一个具有多个派生类的多态基类实现Context的算法逻辑。两者最大的差别就是State模式中派生类持有指向 Context 对象的引用,并通过这个引用调用Context 中的方法,但在 Strategy 模式中就没有这种情况。因此可以说一个 State 实例同样是 Strategy 模式的一个实例,反之却不成立。实际上 State 模式和 Strategy 模式的区别还在于它们所关注的点不尽相同:State 模式主要是要适应对象对于状态改变时的不同处理策略的实现,而 Strategy则主要是具体算法和实现接口的解耦(coupling),Strategy 模式中并没有状态的概念(虽然很多时候有可以被看作是状态的概念),并且更加不关心状态的改变了。

(2)State 模式很好地实现了对象的状态逻辑和动作实现的分离,状态逻辑分布在 State 的派生类中实现,而动作实现则可以放在 Context 类中实现(这也是为什么State派生类需要拥有一个指向 Context 的指针)。这使得两者的变化相互独立,改变 State 的状态逻辑可以很容易复用 Context 的动作,也可以在不影响 State 派生类的前提下创建 Context 的子类来更改或替换动作实现。

(3)State 模式问题主要是逻辑分散化,状态逻辑分布到了很多的 State 的子类中,很难看到整个的状态逻辑图,这也带来了代码的维护问题。

(4)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8428091)。 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦2号

博文不易,支持的请给予小小打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值