学习设计模式 - 状态模式

状态模式

 一丶定义(是什么)

   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设计模式》

 

 

posted @ 2019-07-02 16:16  timfruit  阅读(213)  评论(0编辑  收藏  举报