深入浅出设计模式-012:状态模式(State Pattern)

深入浅出设计模式-012:状态模式(State Pattern)

一:状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像改变了它的类。
    模式将状态封装成独立的类,并将动作委托到代表当前状态的对象。

二:糖果机
    首先,定义一个STATE接口,在这个接口内,糖果机的每个动作都有一个对应的方法。
    然后为机器中的每个状态实现状态类。这些类将负责在对应的状态下进行机器的行为。
    最要,我们要摆脱旧的条件代码,取而代之的方式是将动作委托到状态类。
    让每一个状态“对修改关闭”,让糖果机“多扩展开发”,这样可以加入新的状态类

    class GumballMachine//CONTEXT{
        State soldOutState;
        State noQuarterState;
        State hasQuarterState;
        State soldState;
        State state;
        int count = 0;
        public GumballMachine(int numberGumballs){

            this.soldOutState = new SoldOutState(this);
            this.noQuarterState = new NoQuarterState(this);
            this.hasQuarterState = new HasQuarterState(this);
            this.soldState = new SoldState(this);
            this.count = numberGumballs;
            if (numberGumballs > 0){
                this.state = this.noQuarterState;
            }
            else{
                this.state = this.soldOutState;
            }
        }
        public State StateOfMachine {
            get { return state; }
            set { state = value; }
        }
        public int Count{
            get { return count; }
            set { count = value; }
        }
        public State getSoldOutState{
            get { return soldOutState; }
        }
        public State getNoQuarterState{
            get { return noQuarterState; }
        }
        public State getHasQuarterState{
            get { return hasQuarterState; }
        }
        public State getSoldState{
            get { return soldState; }
        }
        public void insertQuarter(){
            state.insertQuarter();
        }
        public void ejectQuarter(){
            state.ejectQuarter();
        }
        public void turnCrank(){
            state.turnCrank();
        }
        public void dispense(){
            state.dispense();
        }
        public void releaseBall(){
            if (count != 0)
                count -= 1;
        }
    }

    interface State{
        //操作糖果机的四个动作:插入硬币,退回硬币,转动手柄,出糖果
        //糖果机的四个状态:没有硬币,有硬币,售出糖果,糖果售罄
        void insertQuarter();
        void ejectQuarter();
        void turnCrank();
        void dispense();
    }
    class NoQuarterState : State{
        GumballMachine gumballMachine;
        public NoQuarterState(GumballMachine gumballMachine){
            this.gumballMachine = gumballMachine;
        }
        public void insertQuarter() {
            gumballMachine.StateOfMachine = gumballMachine.getHasQuarterState;
        }
        public void ejectQuarter() { }
        public void turnCrank() { }
        public void dispense() { }
    }
    class HasQuarterState : State{       
        GumballMachine gumballMachine;
        public HasQuarterState(GumballMachine gumballMachine){
            this.gumballMachine = gumballMachine;
        }
        public void insertQuarter() { }
        public void ejectQuarter() {
            gumballMachine.StateOfMachine = gumballMachine.getNoQuarterState;
        }
        public void turnCrank(){
            gumballMachine.StateOfMachine = gumballMachine.getSoldState;
        }
        public void dispense() { }
    }
    class SoldState : State{
        GumballMachine gumballMachine;
        public SoldState(GumballMachine gumballMachine){
            this.gumballMachine = gumballMachine;
        }
        public void insertQuarter() { }
        public void ejectQuarter() { }
        public void turnCrank() { }
        public void dispense() {
            gumballMachine.releaseBall();
            if (gumballMachine.Count > 0){
                gumballMachine.StateOfMachine = gumballMachine.getNoQuarterState;
            }
            else{
                gumballMachine.StateOfMachine = gumballMachine.getSoldOutState;
            }
        }
    }
    class SoldOutState : State{      
        GumballMachine gumballMachine;
        public SoldOutState(GumballMachine gumballMachine){
            this.gumballMachine = gumballMachine;
        }
        public void insertQuarter() { }
        public void ejectQuarter() { }
        public void turnCrank() { }
        public void dispense() { }
    }
    static void Main(string[] args)
    {
        GumballMachine gumballMachine = new GumballMachine(5);

        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();
    }

三:在状态机中加入新的状态,即在出糖果时,1/10的概率出2个。加起来就很方便了
    可以考虑把WinnerState类的作用直接放入HasQuarterState盅。
    这样没有符合“一个类,一个责任。”
    1: 构建状态类
        class WinnerState : State
        {
            GumballMachine gumballMachine;
            public WinnerState(GumballMachine gumballMachine)
            {
                this.gumballMachine = gumballMachine;
            }
            public void insertQuarter() { }
            public void ejectQuarter() { }
            public void turnCrank() { }
            public void dispense()
            {
                gumballMachine.releaseBall();
                if (gumballMachine.Count == 0)
                {
                    gumballMachine.StateOfMachine = gumballMachine.getSoldOutState;
                }
                else
                {
                    gumballMachine.releaseBall();
                    if (gumballMachine.Count == 0)
                    {
                        gumballMachine.StateOfMachine = gumballMachine.getSoldOutState;
                    }
                }
            }
        }
    2: 在GumballMachine中加入状态类
        class GumballMachine//CONTEXT
        {
            State winnerState;
        }
    3: 修改HasQuarterState,有这个状态触发
        class HasQuarterState : State
        {
            Random rand = new Random(DateTime.Now.Second);
            public void turnCrank()
            {
                int winner = rand.Next(10);
                if (winner == 0 && gumballMachine.Count > 1)
                {
                    gumballMachine.StateOfMachine = gumballMachine.getWinnerState;
                }
                else
                {
                    gumballMachine.StateOfMachine = gumballMachine.getSoldState;
                }
            }
            public void dispense() { }
        }

四:状态模式允许一个对象基于内部状态而拥有不同的行为。
    和程序状态机不同,状态模式用类代表状态。
    CONTEXT会将当前行为委托给当前状态对象。
    通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。
    状态模式和测试模式拥有相同的雷同,但是他们意图不用。测试模式通常会用行为或算法来配置CONTEXT类。
    状态模式允许CONTEXT随着状态的改变而改变行为。
    状态转换可以由STATE类或CONTEXT类组成
    使用状态模式通常会导致设计中类的数码大量增加
    状态类可以被多个CONTEXT实例共享

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值