21.行为型模式中,如何应用状态模式?

摘要:状态模式 (State Pattern) 状态模式(State)构架出一套完备的事物内部状态转换机制,并将内部状态包裹起来且对外部不可见,使其行为能随其状态的改变而改变,同时简化了事物的复杂的状态变化逻辑。 允许对象在内部状态发生改变时改变
状态模式 (State Pattern) 状态模式(State)构架出一套完备的事物内部状态转换机制,并将内部状态包裹起来且对外部不可见,使其行为能随其状态的改变而改变,同时简化了事物的复杂的状态变化逻辑。 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。 **in short 将一个对象(水)的状态从该对象中分离出来, 封装到专门的状态类(固态, 液态, 气态)中 (用类来表示状态) ,使得对象状态可以灵活变化(状态切换doSwitct(Water context);) ** **例如 '坦克大战'中游戏暂停机制, 可将'游戏对象' 中的所有子弹, 坦克, 位置 朝向状态抽离出来, 可以随时暂停 随时恢复, 使得(游戏)对象状态可以灵活变化; ** 再例如: 当温度变化导致水的状态发生变化时,它就会有不同的行为,如冰会滚动、水会流动、水蒸气则会漂浮,体积,单位质量均不一样. 水在0℃状态呈固态 体积小; 在常温下的呈液态 体积中,以及100℃以上时 呈气态 体积最大; UML类图 代码实例 1. 水 (Context对象) public class Water { private State state; public State getState() { return state; } //设置 状态 public void setState(State state) { this.state = state; this.state.doSwitct(this); } public void flow() { this.state.doFlow(); } public void rolling() { this.state.doRolling(); } } 2.抽象状态定义及其特性实现 (固态, 液态,气态) /** * 抽象状态定义 **/ public interface State { /** * 状态切换 */ void doSwitct(Water context); /** * 流动 (状态特性方法) */ void doFlow(); /** * 滚动.. (状态特性方法) */ void doRolling(); } /** * 固态特性 * @author yangfh * @date 2023-12-06 20:57 **/ public class SolidityState implements State{ @Override public void doSwitct(Water context) { System.out.println("将 "+ context+", 状态切换为固态"); } @Override public void doFlow() { System.out.println("当前是固态, 也不能流动..."); } @Override public void doRolling() { System.out.println("当前是固态, 飞砂走石"); } } /** * 液态特性 * @author yangfh * @date 2023-12-06 20:57 **/ public class LiquidState implements State{ @Override public void doSwitct(Water context) { System.out.println("将 "+ context+", 状态切换为液态"); } @Override public void doFlow() { System.out.println("当前是液态, 小桥流水人家.."); } @Override public void doRolling() { System.out.println("当前是液态, 不能滚动"); } } /** * 气态特性 * @author yangfh * @date 2023-12-06 20:57 **/ public class GaseousState implements State{ @Override public void doSwitct(Water context) { System.out.println("将 "+ context+", 状态切换为气态"); } @Override public void doFlow() { System.out.println("当前是气态, 不能流动"); } @Override public void doRolling() { System.out.println("当前是气态, 不能滚动"); } } 3.测试 public static void main(String[] args) { System.out.println("========常温环境========="); // 常温环境: 液态状态 State state = new LiquidState(); //水 (Context)Water content = new Water(); content.setState(state); content.flow(); content.rolling(); System.out.println("========低温环境========="); State state2 = new SolidityState(); content.setState(state2);//设置状态 content.flow(); content.rolling(); } /**out ========常温环境========= 将 org.yang.mca.pattern21.Water@6b71769e, 状态切换为液态 当前是液态, 小桥流水人家.. 当前是液态, 不能滚动 ========低温环境========= 将 org.yang.mca.pattern21.Water@6b71769e, 状态切换为固态 当前是固态, 也不能流动, 只能滚动... 当前是固态, 飞砂走石 **/ 状态模式总结 关键角色 上下文对象 Water 状态抽象 State 具体状态实现 SolidityState (将上下文对象, 传递过来切换其状态) 状态模式优缺点 1) 状态模式的优点: 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 2) 状态模式的缺点: 状态模式的使用必然会增加系统类和对象的个数。 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 状态模式对"开闭原则"的支持并不太好 (添加新的状态类需要修改那些负责状态转换的源代码) 状态模式适用使用场景 对象根据自身状态的变化来进行不同行为的操作时, 比如,购物订单状态。 对象需要根据自身变量的当前值改变行为,不期望使用大量 if-else 语句时, 比如,商品库存状态。 对于某些确定的状态和行为,不想使用重复代码时, 比如,某一个会员当天的购物浏览记录。