介绍
状态模式(State Pattern)当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式中的行为是由状态来决定的,不同的状态下有不同的行为。
状态模式和策略模式的结构几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立的、可相互替换的。用一句话来表述,状态模式把对象的行为封装在不同的状态对象里,每个状态对象都有一个共同的抽象状态基类。状态模式的意图是让一个对象在其内部状态改变时,其行为也随之改变。
优缺点
优点
状态模式将所有与一个特定的状态相关的行为都放入一个状态对象中,它提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性和可维护性。
缺点
增加系统类和对象的个数
使用场景
- 行为随状态改变而改变的场景。
- 条件、分支语句( if-else 或 switch-case )的代替者。
注意事项:
在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
举例
以电视遥控器为例,首先将电视的状态分为开机状态和关机状态,在开机状态下可以通过遥控器进行频道切换、音量调整等操作,但是此时重复按开机键是无效的;而在关机状态下,频道切换、音量调整、关机都是无效操作,只有按开机按钮才会生效,也就是说电视的内部状态决定了遥控器的行为。
我们将状态用对象来替换,将行为封装到对象中,使得在不同状态下有不同的实现
电视状态接口类
public interface TvState {
void nextChannel();
void prevChannel();
void turnUp();
void turnDown();
}
开机状态类
public class PowerOnState implements TvState {
@Override
public void nextChannel() {
System.out.println("下一频道");
}
@Override
public void prevChannel() {
System.out.println("上一频道");
}
@Override
public void turnUp() {
System.out.println("调高音量");
}
@Override
public void turnDown() {
System.out.println("调低音量");
}
}
关机状态类
public class PowerOffState implements TvState {
@Override
public void nextChannel() {
}
@Override
public void prevChannel() {
}
@Override
public void turnUp() {
}
@Override
public void turnDown() {
}
}
电源接口类
public interface PowerController {
void powerOn();
void powerOff();
}
遥控器类
public class TvController implements PowerController {
private TvState mTvState;
private void setTvState(TvState tvState){
this.mTvState = tvState;
}
@Override
public void powerOn() {
System.out.println("开机");
setTvState(new PowerOnState());
}
@Override
public void powerOff() {
System.out.println("关机");
setTvState(new PowerOffState());
}
public void nextChannel(){
mTvState.nextChannel();
}
public void prevChannel(){
mTvState.prevChannel();
}
public void turnUp(){
mTvState.turnUp();
}
public void turnDown(){
mTvState.turnDown();
}
}
客户端调用类
public class Client {
public static void main(String[] args) {
TvController tvController = new TvController();
// 开机
tvController.powerOn();
// 下一频道
tvController.nextChannel();
// 关机
tvController.powerOff();
// 下一频道
tvController.nextChannel();
}
}
输出结果
开机
下一频道
关机