在软件设计中经常会遇到这样的对象转移的条件表达式过于复杂的情况,这时可以采用if else或者switch case等语句进行处理,但是这样做的弊端就在于每增加一次状态,都需要对以前的代码进行修改,这不符合面向对象的开闭原则。此时更好的方法就是将状态的判断逻辑转移到表示不同状态的一系列类中,这就是今天要介绍的状态模式。
状态模式的定义,允许一个对象在其内部状态改变时改变它的行为。
状态模式的UML图:
状态模式涉及到以下角色:
环境(Context)角色::定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
举一个现实生活中的例子,我们在调节显示屏的亮度和色度的时候,当处于不同的模式时,按增加和减少键,显示器做出的反应是不同的,这个问题我们可以用if else 来处理,但是如果显示屏增加了调节对比度选项时,就得修改之前的程序,增加新的选项,显然采用状态模式实现的程序更健壮,可维护性更强。
采用C++实现这个例子:
#include "stdafx.h"
#include<iostream>
using namespace std;
class ScreenState
{
public:
virtual void increase() = 0;
virtual void decrease() = 0;
};
class LuminanceState :public ScreenState //亮度调节状态
{
public:
virtual void increase()
{
cout << "亮度增加!" << endl;
}
virtual void decrease()
{
cout << "亮度减少!" << endl;
}
};
class ContrastState :public ScreenState //对比度调节状态
{
public:
virtual void increase()
{
cout << "对比度度增加!" << endl;
}
virtual void decrease()
{
cout << "对比度度减少!" << endl;
}
};
class ColourState :public ScreenState //色度调节状态
{
public:
virtual void increase()
{
cout << "色度增加!" << endl;
}
virtual void decrease()
{
cout << "色度减少!" << endl;
}
};
class Screen
{
public:
Screen(ScreenState *state) :mScreenState(state){}
void increase()
{
mScreenState->increase();
}
void decrease()
{
mScreenState->decrease();
}
void switchMode(ScreenState *state)
{
mScreenState = state;
}
private:
ScreenState *mScreenState;
};
int _tmain(int argc, _TCHAR* argv[])
{
LuminanceState luminanceState;
ContrastState contrastState;
ColourState colourState;
Screen screen(&luminanceState);
screen.decrease();
screen.increase();
screen.switchMode(&contrastState);
screen.decrease();
screen.increase();
screen.switchMode(&colourState);
screen.decrease();
screen.increase();
return 0;
}
运行结果: