浅析设计模式之八 状态模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析设计模式之八 状态模式相关的知识,希望对你有一定的参考价值。

传统的状态大都是这样的(状态模式)

public class GumballMachine {
    final static int SOLD_OUT = 0;
    final static int NO_QUARTER = 1;
    final static int HAS_QUARTER = 2;
    final static int SOLD = 3;
    
    
    
}
然后嵌入大量的if - else
根究当前状态来进行某些操作,但是呢,现在我们是学过设计模式的人了,我们总是想搞出点幺蛾子来封装一下我们想要的东西,换句话说,我们要遵守"封装变化"原则
创建一个接口,填充我们需要的某些行为
/**
 * 状态接口
 * @author Dougest 2017年7月16日    下午11:19:57
 *
 */
public interface State {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}

然后通过几个实现类来实现我们不同状态写的具体细节

/**
 * 状态实现类
 * @author Dougest 2017年7月16日    下午11:19:57
 *
 */
public class SoldState {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}
/**
 * 状态实现类
 * @author Dougest 2017年7月16日    下午11:19:57
 *
 */
public class SoldOutState {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}
/**
 * 状态实现类
 * @author Dougest 2017年7月16日    下午11:19:57
 *
 */
public class NoQuarterState {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}
/**
 * 状态实现类
 * @author Dougest 2017年7月16日    下午11:19:57
 *
 */
public class HasQuarterState {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}
现在来具体实现
接口不变,实现新的调用类
/**
 * 
 * @author Dougest 2017年7月17日    上午12:10:47
 *
 */
public class CompleMachine {
    State noQuarterState;
    State hasQuarterState;
    State soldOutState;
    State soldState;
    
    State state = soldOutState;
    int count = 0;
    
    
    public CompleMachine(int numberCompleMachine) {
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldOutState = new SoldOutState(this);
        soldState = new SoldState(this);
        this.count = numberCompleMachine;
        
        if(numberCompleMachine > 0)
            state = noQuarterState;
    }
    
    public void insertQuarter() {
        state.insertQuarter();
        
    }
    public void ejectQuarter() {
        state.ejectQuarter();
    }
    public void turnCrank() {
        state.turnCrank();
        state.dispense();
    }
    void setState(State state) {
        this.state = state;
    }
    
    void releaseBall() {
        if(count != 0)
            count = count -1;
    }
    
    public int getCount() {
        return this.count;
    }
    public State getNoQuarterState() {
        return noQuarterState;
    }
    public void setNoQuarterState(State noQuarterState) {
        this.noQuarterState = noQuarterState;
    }
    public State getHasQuarterState() {
        return hasQuarterState;
    }
    public void setHasQuarterState(State hasQuarterState) {
        this.hasQuarterState = hasQuarterState;
    }
    public State getSoldOutState() {
        return soldOutState;
    }
    public void setSoldOutState(State soldOutState) {
        this.soldOutState = soldOutState;
    }
    public State getSoldState() {
        return soldState;
    }
    public void setSoldState(State soldState) {
        this.soldState = soldState;
    }
    public State getState() {
        return state;
    }
    public void setCount(int count) {
        this.count = count;
    }

简单的实现某一个状态对象

/**
 * 状态实现类
 * @author Dougest 2017年7月17日    上午12:11:16
 *
 */
public class HasQuarterState implements State {
    private CompleMachine compleMachine;
    
    public HasQuarterState(CompleMachine compleMachine) {
        this.compleMachine = compleMachine;
    }
    
    
    @Override
    public void insertQuarter() {
        System.out.println("");
    }
    @Override
    public void ejectQuarter() {
        System.out.println("");
    }
    @Override
    public void turnCrank() {
        System.out.println("");
    }
    @Override
    public void dispense() {
        compleMachine.releaseBall();
        if(compleMachine.getCount() > 0)
            compleMachine.setState(compleMachine.getHasQuarterState());
        else 
            compleMachine.setState(compleMachine.getSoldOutState());
    }
现在我们已经做到了如下几点
1.将每个状态的行为局部化到他自己的类中
2.将容易的产生问题的if语句删除,方便日后维护
3.让每一个状态对修改关闭,对扩展开放,因为可以加入新的状态
4.创建了一个新的代码基和类,更能映射我们关于状态的业务逻辑,更容易阅读和理解
 
上面的代码我们实现了定义状态模式
定义状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修了他的类
 
这个就有点我们前面讲的命令模式的味道了,定义状态模式将状态封装成对象,并将动作委托给代表当前状态的对象,我们知道行为会随着内部状态而改变
 
这里有一个习惯,如果没有共同的功能可以放在抽象类中,我们通常使用接口,就比如这个demo
 技术分享

 

 
要点:
状态模式允许一个对象基于内部的状态而拥有不同的行为
和程序状态机(PSM)不同,状态模式用类代表状态
context会将行为委托给当前状态对象
通过将每一个状态封装成对象,我们把以后需要做的任何改变局部化了
状态模式和策略模式有相同的类图,但是他们的意图不一样
策略模式通常会用行为或者算法来配置context类
状态模式允许context类随着状态的改变而改变行为
状态转换可以有State类或者context类控制
使用状态模式通常会使设计中出现大量的类
状态类可以被多个context共享
 

 

 

 

 

 

 

 

以上是关于浅析设计模式之八 状态模式的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用片段保存夜间模式状态

Java设计模式之八 ----- 责任链模式和命令模式

设计模式之八:组合模式(Composite Pattern)

Java进阶篇设计模式之八 ----- 责任链模式和命令模式

java23种设计模式之八: 工厂方法模式

浅析设计模式之享元设计模式