学习设计模式 - 状态模式
状态模式
一丶定义(是什么)
Allow an object to alter its behavior when its internal state changes. The object will appear to change tis class. (当一个对象内在状态改变时,允许其改变其行为,这个对象像是改变了其类。)
状态模式的核心在于封装,状态的变更引起了行为的变更,从外部看起来像这个对象对应的类发生了改变一样。
二丶为什么
当某件事物的"行为"跟随着不同的"状态"而发生变化时,可以将对应的行为封装(委托)到对应的状态实体对象中,如此一来,降低了问题的复杂度,不用再全局考虑状态和行为对应的变化,只专注于当前状态的行为变化即可。同时也避免了诸多if...else代码。
三丶例子
1. 糖果机,各状态上下文
/** * 糖果机 * (各状态的上下文, 可获取各个状态) * @author TimFruit * @date 2019/5/19 13:40 */ public class GumballMachine{ // --------------------------------- 糖果机对应的各个状态 private State soldState; private State soldOutState; private State noQuarterState; private State hasQuarterState; // ---------------------------------- /** * 糖果机当前的状态 */ private State currState; /** * 糖果数 */ private int count=0; public GumballMachine(int gumballCount) { this.count = gumballCount; this.soldState=new SoldState(this); this.soldOutState=new SoldOutState(this); this.noQuarterState=new NoQuarterSate(this); this.hasQuarterState=new HasQuarterSate(this); if(this.count<=0){ this.currState=this.soldOutState; }else { this.currState=this.noQuarterState; //刚开始是没有投硬币 } } // ------------------------------------------------ // 糖果机对外暴露的行为, 内部委托给对应的状态处理 // ------------------------------------------------ public void insertQuarter() { //客人投入硬币 this.currState.insertQuarter(); } public void ejectQuarter() { //退出硬币 this.currState.ejectQuarter(); } public void turnCrank() { this.currState.turnCrank(); //客人转动曲柄 this.currState.dispense(); //发放糖果 } // ------------------------------ // setter // ------------------------------ public void setCurrState(State currState) { this.currState = currState; } public void setCount(int count) { this.count = count; } // ----------------------------- // getter // ----------------------------- public State getSoldState() { return soldState; } public State getSoldOutState() { return soldOutState; } public State getNoQuarterState() { return noQuarterState; } public State getHasQuarterState() { return hasQuarterState; } public State getCurrState() { return currState; } public int getCount() { return count; } // ---------------------------- @Override public String toString() { return "糖果机还有"+this.count+"颗糖果"; } }
2. state状态
/** * 糖果机的"状态" * * 糖果机所有的行为委托给对应的"状态" * */ public interface State { /** * 投硬币 */ void insertQuarter(); /** * 弹出(退出)硬币 */ void ejectQuarter(); /** * 转动曲柄 */ void turnCrank(); /** * 发放糖果 */ void dispense(); }
3. 各具体状态
/** * 有25分钱 * 即 已投硬币 * @author TimFruit * @date 2019/5/19 13:33 */ public class HasQuarterSate implements State { private GumballMachine machine; public HasQuarterSate(GumballMachine gumballMachine) { this.machine = gumballMachine; } @Override public void insertQuarter() { System.out.println("已投入25分硬币,不能再投入硬币..."); } @Override public void ejectQuarter() { System.out.println("退回硬币..."); this.machine.setCurrState(this.machine.getNoQuarterState()); } @Override public void turnCrank() { System.out.println("转动曲柄..."); this.machine.setCurrState(this.machine.getSoldState()); } @Override public void dispense() { //当前状态下,不恰当的行为 } }
/** * 没有25分钱 * 即没有投硬币 * @author TimFruit * @date 2019/5/19 13:32 */ public class NoQuarterSate implements State { private GumballMachine machine; public NoQuarterSate(GumballMachine gumballMachine) { this.machine = gumballMachine; } @Override public void insertQuarter() { System.out.println("投入25分硬币..."); this.machine.setCurrState(machine.getHasQuarterState()); } @Override public void ejectQuarter() { //当前状态下,不恰当的行为 } @Override public void turnCrank() { //当前状态下,不恰当的行为 } @Override public void dispense() { //当前状态下,不恰当的行为 } }
/** * 糖果机售出糖果 * @author TimFruit * @date 2019/5/19 13:30 */ public class SoldState implements State { private GumballMachine machine; public SoldState(GumballMachine gumballMachine) { this.machine = gumballMachine; } @Override public void insertQuarter() { //当前状态下,不恰当的行为 } @Override public void ejectQuarter() { //当前状态下,不恰当的行为 } @Override public void turnCrank() { //当前状态下,不恰当的行为 } @Override public void dispense() { int count=this.machine.getCount(); if(count>0){ System.out.println("发放1个糖果..."); count=count-1; this.machine.setCount(count); this.machine.setCurrState(this.machine.getNoQuarterState()); }else { this.machine.setCurrState(this.machine.getSoldOutState()); } } }
/** * 已售完状态 * @author TimFruit * @date 2019/5/19 13:31 */ public class SoldOutState implements State { private GumballMachine machine; public SoldOutState(GumballMachine gumballMachine) { this.machine = gumballMachine; } @Override public void insertQuarter() { //当前状态下,不恰当的行为 } @Override public void ejectQuarter() { //当前状态下,不恰当的行为 } @Override public void turnCrank() { //当前状态下,不恰当的行为 } @Override public void dispense() { //当前状态下,不恰当的行为 } }
4. 运行结果
投入25分硬币...
转动曲柄...
发放1个糖果...
糖果机还有4颗糖果
投入25分硬币...
退回硬币...
糖果机还有4颗糖果
完整源码:点此查看
学习资料:
《HeadFirst设计模式》
人生没有彩排,每一天都是现场直播