1.定义
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同抽象状态基类。状态模式的意图是让一个对象在其内部状态改变的时候其行为也随之改变。
2.使用场景
1)一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
2)代码中包含大量与对象状态有关的条件语句,例如一个操作中含有庞大的多分支语句,且这些分支依赖于该对象的状态。
3.简单实现
将电视的状态分为开机和关机状态,在开机状态下遥控器可以切换频道,调整音量,此时重复按开机键是无效的;在关机状态下,频道切换、调解音量关机键都是无效的,只有按开机才会生效。
普通实现:
//遥控器 public class TVController { //开机状态 private final static int POWER_ON = 1; //关机状态 private final static int POWER_OFF = 2 ; //当前状态 private int state = POWER_OFF; //开机按钮 public void powerON(){ if (state == POWER_OFF){ System.out.println("开机了..."); } state = POWER_ON; } //关机按钮 public void powerOFF(){ if (state == POWER_ON){ System.out.println("关机了..."); } state = POWER_OFF; } //切换频道 public void changeChannel(){ if (state == POWER_ON){ System.out.println("频道切换..."); }else { System.out.println("Tips : 未开机"); } } //调节音量 public void turnVoice(){ if (state == POWER_ON){ System.out.println("音量调解..."); }else { System.out.println("Tips : 未开机"); } } }
通过state字段来存储电视机的状态,各个操作根据state字段的状态来判断是否执行。随着后期状态或者功能增加,就要不断维护if...else 语句,代码会变得重复切混乱。我们用状态模式来改造它。
//定义电视功能接口 interface TvState{ //切换频道 void changeChannal(); //调节音量 void turnVoice(); } //关机状态 所用功能都无效 class PowerOffState implements TvState{ @Override public void changeChannal() { System.out.println("未开机...切换频道无效"); } @Override public void turnVoice() { System.out.println("未开机...调解音量无效"); } } //开机状态 class PowerOnState implements TvState{ @Override public void changeChannal() { System.out.println("频道切换..."); } @Override public void turnVoice() { System.out.println("音量调节..."); } } //状态接口 interface PowerController{ //开机状态 void powerOn(); //关机状态 void powerOff(); } //遥控器 class TvContorller implements PowerController{ TvState tvState; public void setTvState(TvState state){ this.tvState = state; } @Override public void powerOn() { setTvState(new PowerOnState()); System.out.println("开机..."); } @Override public void powerOff() { setTvState(new PowerOffState()); System.out.println("关机..."); } //切换频道 public void changeChannal(){ tvState.changeChannal(); } public void turnVoice(){ tvState.turnVoice(); } } public class StateMode { public static void main(String[] arg){ TvContorller tvContorller = new TvContorller(); //设置开机状态 tvContorller.powerOn(); tvContorller.changeChannal(); tvContorller.turnVoice(); //设置关机状态 tvContorller.powerOff(); //已关机 无法切换频道 tvContorller.changeChannal(); } }
输出:
4.小结
优点:
将所有与一个特定的状态相关的行为都放在一个状态对象中,它提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了拓展性和可维护性。
缺点:
会增加系统类和对象的个数。