1、介绍
状态模式中的行为是由状态决定的,不同的状态有不同的行为。状态模式与策略模式的结构一样的,但它们的目的和本质不同,状态模式的行为是平行的,不可替换的,而策略模式的行为是对立的,可替换的。
2、定义
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
当一个对象的内在类改变时允许改变其行为,这对象看起来像是改变了其类。
3、使用场景
- 对象的行为依赖它所处的状态,并且在运行是根据状态改变它的行为
- 代码中含有大量的跟状态有关的条件语句。
4、UML类图
角色说明:
- Context:屏蔽高层模块对行为的直接访问,它持有一个State类的引用
- State:对每个行为的抽象
- ConcreteStateA、ConcreteStateB:具体的行为类。
5、示例
以遥控器为例来说明状态模式的实现。首先状态模式分为开机和关机状态,在开启状态下,可以进行切换频道、关机操作,但重复开机按键无效;在关机状态下,切换频道和重复关机无效,只能先进行开机操作。
首先看一下普通的实现方式。
/**
* 电视控制类,含有开机、关机、下一个频道、上一个频道的功能
* @author Administrator
*
*/
public class TVController1 {
private final static int POWER_ON = 1;
private final static int POWER_OFF = 2;
private int mState = POWER_OFF;
public void powerOn(){
if (mState == POWER_OFF) {
System.out.println("开机了");
}
mState = POWER_ON;
}
public void powerOFF(){
if (mState == POWER_ON) {
System.out.println("关机了");
}
mState = POWER_OFF;
}
public void nextChannel(){
if (mState == POWER_ON) {
System.out.println("下一个频道");
}else {
System.out.println("抱歉,没有开机");
}
}
public void preChannel(){
if (mState == POWER_ON) {
System.out.println("上一个频道");
}else {
System.out.println("抱歉,没有开机");
}
}
}
在TVController类中,同名mState存储电视状态,在进行频道切换时,必须通过if-else进行条件判断进行操作,代码重复,相对较为混乱。
接下来,通过状态模式来实现。
/**
* 状态接口
* @author Administrator
*
*/
public interface TVState {
public void nextChannel();
public void preChannel();
}
/**
* 具体状态实现类,开机状态
* @author Administrator
*
*/
public class PowerOnState implements TVState {
@Override
public void nextChannel() {
System.out.println("下一个频道");
}
@Override
public void preChannel() {
System.out.println("上一个频道");
}
}
/**
* 具体状态实现,关机状态
*/
public class PowerOffState implements TVState{
@Override
public void nextChannel() {
System.out.println("抱歉,请先开机");
}
@Override
public void preChannel() {
System.out.println("抱歉,请先开机");
}
}
/**
* 电源操作接口
*/
public interface PowerController {
public void powerOn();
public void powerOff();
}
public class TVController implements PowerController{
private TVState mState = null;
public void setState(TVState state) {
this.mState = state;
}
public void nextChannel(){
mState.nextChannel();
}
public void preChannel() {
mState.preChannel();
}
@Override
public void powerOn() {
setState(new PowerOnState());
System.out.println("开机了");
}
@Override
public void powerOff() {
setState(new PowerOffState());
System.out.println("关机了");
}
}
/**
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
TVController controller = new TVController();
controller.powerOn();
controller.nextChannel();
controller.preChannel();
controller.powerOff();
controller.nextChannel();
controller.preChannel();
}
}
输出结果如下:
开机了
下一个频道
上一个频道
关机了
抱歉,请先开机
抱歉,请先开机
6、总结
优点:State模式将所有与一个状态对象有关的行为组织成一个接口类,统一管理,结构清晰,避免代码臃肿,同时也保证了可扩展性和可维护性
缺点:子类太多,不易管理