小侃设计模式(廿一)-状态模式
1.概述
状态模式(State Pattern)是行为型设计模式的一种,它主要用来解决对象存在多种状态转换时,需要对外输出不同的行为。状态模式与策略模式有一定相似,区别在于策略模式行为彼此独立,可以进行相互替换;状态模式将对象状态封装在不同对象中,不同状态显示不同行为,不同状态之间可能有触发条件和先后关系。状态模式相较于策略模式而言,客户端不需要关心当前对象的状态,而策略模式需要在客户端根据状态选择调用策略类。本文将详述状态模式的原理及使用。
2.原理及使用
2.1 原理
状态模式的UML类图如下所示:
类图中主要包含三个元素:抽象状态角色(State)、具体状态角色(ConcreteState)、环境类角色(Context)。具体解释如下:
抽象状态角色(State):定义一个接口,封装环境对象中的特定状态所对应的行为,接口中可以有一个或多个行为;
具体状态角色(ConcreteState):是State的实现,定义了具体的行为,在不同的场景下进行状态切换;
环境类角色(Context):定义了一个接口,内部维护一个当前状态,根据不同的状态进行具体状态角色切换,产生不同行为。
2.2 案例
有一个MP3播放器,有开始、停止、下一首、上一首等功能,这里主要以开始和结束状态为准。
根据状态模式,画出UML类图如下:
编码如下:
public interface State {
void print();
void handle(Context context);
}
public class StartState implements State {
@Override
public void print() {
System.out.println("Start ......");
}
@Override
public void handle(Context context) {
System.out.println("开始播放。。。");
context.setState(this);
}
}
public class StopState implements State {
@Override
public void print() {
System.out.println("STOP ......");
}
@Override
public void handle(Context context) {
System.out.println("停止播放。。。");
context.setState(this);
}
}
public class Context {
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void handle() {
state.handle(this);
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context();
State startState = new StartState();
startState.handle(context);
System.out.print("当前状态:");
context.getState().print();
State stopState = new StopState();
stopState.handle(context);
System.out.print("当前状态:");
context.getState().print();
}
}
运行结果为:
2.3 优点和缺点
2.3.1 优点
1.代码有很强的可读性: 状态模式将每个状态的行为封装到对应的一个类中,使代码可读性更高;
2.方便维护: 避免大量的if…else语句,使代码更清晰一些;
3.符合开闭原则: 容易增加和删除状态。
2.3.1 缺点
1.容易造成类爆炸:当事件状态较多时,实现类会剧增;
2.容易造成代码混乱:当事件状态较多时,容易造成代码混乱;
3.小结
1.状态模式适用于行为随着状态而改变的场景,或者替换代码中存在的大量if…else语句;
2.状态模式能在一定程度上增加代码可读性。
4.参考文献
1.《设计模式之禅》-秦小波著
2.《大话设计模式》-程杰著
3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式
4.https://www.runoob.com/design-pattern/observer-pattern.html