设计模式笔记-State模式

原创 2016年05月31日 21:07:45

状态模式:事物在不同状态下会有不同表现(动作),经过不同动作后,又会转移到下一个不同的状态。这种问题可以用Switch/Case(if-else)搞定, 但如果case语句很多,就很麻烦,这种实现也没有将逻辑和动作分离,后期维护得不到保证!加case语句要修改原来代码,违反了“对扩展开放,对修改关闭”的原则!State 模式将每一个case分支都封装到独立的类中!

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


上下文环境(Context):定义客户需要的接口并维护一个ConcreteState实例,将与状态相关的操作委托给它来处理。

抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

具体状态(Concrete State):实现象状态定义的接口, 每一子类实现一个与Context的一个状态相关的行为。 

这个状态模式,网上的实现我觉得都不怎么好,主要是实现细节方面的!

这一篇,每次状态转换都new一个对象,delete一个对象,申请&释放内存好像挺耗时的!它描述的状态不是封闭的,我自己在实现的时候,就出现了问题--说出来可能丢人,就是new一个对象传入时,如果对象定义在后面C++是识别不到的,前向声明也没用,只能把.h和.cpp文件分开写,然后互相包含对方的.h文件!

另一篇,我觉得实现的很好,不过是PHP版本的,PHP是弱类型语言,有一些方便之处,比如所有状态类事先在Context类构造函数中new好。我在用C++改写时遇到了问题,什么头文件你包含我,我包含你的,太烦了,没成功!就简化成下面这样吧,不停申请&释放是挺耗时的。可以理解为一个开关,只有开和关两种状态!

class Context;

class LiftState {
public:
	LiftState();
	virtual ~LiftState();
	virtual void open(Context*) = 0;
	virtual void close(Context*) = 0;
};

class Context
{
public:

	Context();
	~Context();
	void setLiftState(LiftState* ls);
	LiftState* getLiftState();
	void open();
	void close();
private:
	LiftState* m_liftState;
};
LiftState::LiftState() {}

LiftState::~LiftState() {}

Context::Context() { m_liftState = NULL; }
Context::~Context() {}
void Context::setLiftState(LiftState* ls) {
	if (m_liftState) delete m_liftState;
	m_liftState = ls;
}
LiftState* Context::getLiftState() { return m_liftState; }
void Context::open() { m_liftState->open(this); }
void Context::close() { m_liftState->close(this); }
class OpenState : public LiftState {
public:
	OpenState();
	void open(Context* );
	void close(Context* );
};
OpenState::OpenState() {}
void OpenState::open(Context* ctx) {}

void OpenState::close(Context* ctx) {
	cout << "open->close!" << endl;
	ctx->setLiftState(new CloseState());
	ctx->getLiftState()->close(ctx);
}
#include"openstate.h"

class CloseState : public LiftState {
public:
	CloseState();
	void open(Context* );
	void close(Context* );
};
#include"openstate.h"
#include"closestate.h"

CloseState::CloseState() {}
void CloseState::open(Context* ctx) {
	cout << "close->open!" << endl;
	ctx->setLiftState(new OpenState());
	ctx->getLiftState()->open(ctx);
}

void CloseState::close(Context* ctx) {}
用户代码:

int main()
{
	Context* ct = new Context();
	ct->setLiftState(new OpenState());
	ct->open();
	ct->close();
	ct->open();
	return 0;
}

如果有想测试这个代码的,记得把各个代码块分文件存放!因为两个状态的CPP文件相互包含了对方的头文件,相互包含只能是声明,不能是定义!

代码里,state类里是通过传参的方式使用Context类的,而不能组合一个Context*类型的变量,因为Context类里已经组合了一个State*的变量了,相互包含的话,上面那条delete语句后,把调用setLiftState函数的指针对象自身都删除了,因为删除的State类对象指针中包含了Context对象指针!

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

设计模式(c++)笔记之十五(State模式)

一、描述       概念:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 问题:       每个人、事物在不同的状态下会有不同表现(动作),而一...

设计模式之State模式(笔记)

状态模式:当一个对象的内在状态发生改变时允许改变其内在行为,这个对象看起来像是改变了其类。 状态模式主要是解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状...

设计模式State模式源码

  • 2009年11月18日 11:12
  • 208KB
  • 下载

State模式详解--设计模式(15)

State模式来源:         每个人、事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State)。最简单的一个生活中的例子就是:地铁入口处,如果你...

设计模式的解析和实现(C++)之十七-State模式

作用:     允许一个对象在其内部状态改变时改变它的行为。     UML结构图:     解析:     State模式主要解决的是在开发中时常遇到的根据不同的状态需要进行不同...

c++设计模式(9)-State模式

作用:允许一个对象在其内部状态改变时改变它的行为.UML结构图:解析:       State模式主要解决的是在开发中时常遇到的根据不同的状态需要进行不同的处理操作的问题,而这样的问题,大部分人是采用...

常见设计模式的解析和实现(C++)之十七-State模式

作用: 允许一个对象在其内部状态改变时改变它的行为. UML结构图: 解析: State模式主要解决的是在开发中时常遇到的根据不同的状态需要进行不同的处理操作的问题,而这样的问题,...

设计模式之State模式

State模式类似于switch的多路分钟功能:

设计模式之state模式

《设计模式》对状态模式的定义:允许一个对象在其状态改变时,改变它的行为。 《设计模式》对状态模式的定义:允许一个对象在其状态改变时,改变它的行为。看起来对象似乎修改了它的类。...

设计模式之state模式(一)

// 详细代码请从我的资源中下载 // 状态模式主要用来解决的是当控制一个对象转换的条件表达式过于复杂时的情况。 // 把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式笔记-State模式
举报原因:
原因补充:

(最多只允许输入30个字)