状态模式
声明:本文章参考《设计模式》 gof。概念与定义均为书中描述。
1. 意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
2. 适用性
在下面的两种情况下均可使用 State模式:
• 一个对象的行为取决于它的状态 , 并且它必须在运行时刻根据状态改变它的行为。
• 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
3.结构图
代码:
#pragma once
#include "stdafx.h"
class ConText;
class State
{
public:
virtual ~State() {}
virtual void handle(ConText * context) = 0;
};
class ConText
{
public:
ConText(State * sta) :state(sta)
{
}
~ConText()
{
if (state)
{
delete state;
}
}
void Request()
{
state->handle(this);
}
void changeState(State * sta)
{
if (state) //防止类存泄漏
{
delete state;
}
state = sta;
}
private:
State * state;
};
class ConcreteStateA : public State
{
public:
void handle(ConText * context);
};
class ConcreteStateB : public State
{
public:
void handle(ConText * context);
};
class ConcreteStateC : public State
{
public:
void handle(ConText * context);
};
void ConcreteStateA::handle(ConText * context)
{
cout << "ConcreteStateA change" << endl;
context->changeState(new ConcreteStateB);
}
void ConcreteStateB::handle(ConText * context)
{
cout << "ConcreteStateB change" << endl;
context->changeState(new ConcreteStateC);
}
void ConcreteStateC::handle(ConText * context)
{
cout << "ConcreteStateC change" << endl;
context->changeState(new ConcreteStateA);
}
void process()
{
ConText *context = new ConText(new ConcreteStateA());// 这个时候请求的是ConcreteStateA 状态
//改变下个状态
context->Request(); //发送变化 这个时候ConcreteStateA 变成了ConcreteStateB 状态
context->Request(); //发送变化 这个时候ConcreteStateB变成了ConcreteStateC 状态
context->Request(); //发送变化 这个时候ConcreteStateC变成了ConcreteStateA 状态
context->Request(); //发送变化 这个时候ConcreteStateA变成了ConcreteStateB 状态
}
输出结果:
ConcreteStateA change
ConcreteStateB change
ConcreteStateC change
ConcreteStateA change
优点与缺点:
切换状态非常明了,但是这样会加大子类的数量。
这里简单记录一下笔记,详细设计模式可以看对应专业的书。