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

    技术2025-01-15  16

    深入浅出设计模式-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实例共享

     

    最新回复(0)