3-2设计模式之状态模式(State)

3.2.1 模式意图:

根据对象内部状态的不同,而产生的不同行为,常规会直接采用if else语句,但是随着状态的增多,常规方式多会造成系统耦合度的增加,bug出现几率升高,当遇到这类情况时,可以使用状态模式进行重构。

3.2.2 模式概念:

它属于行为型模式,允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

3.2.3 模式元素:

  • 上下文(Context)
  • 状态类抽象(State)
  • 状态类细节(ConcreteStateA、ConcreteStateB等)

3.2.4 代码示例:

A.状态相关

    public abstract class State
    {
        protected Context context = null;

        public State(Context context)
        {
            this.context = context;
        }
        public abstract void Handle(string value);
    }
    public class ConcreteStateA : State
    {
        public ConcreteStateA(Context context) : base(context)
        { }

        public override void Handle(string value)
        {
            Debug.Log("ConcreteStateA.Handle");
            if (value == "喜")
                context.SetState(new ConcreteStateB(context));
        }

    }
    public class ConcreteStateB : State
    {
        public ConcreteStateB(Context context) : base(context)
        { }

        public override void Handle(string value)
        {
            Debug.Log("ConcreteStateB.Handle");
            if (value == "喜")
                context.SetState(new ConcreteStateC(context));
        }

    }
    public class ConcreteStateC : State
    {
        public ConcreteStateC(Context context) : base(context)
        { }

        public override void Handle(string value)
        {
            Debug.Log("ConcreteStateC.Handle");
            if (value == "喜")
                context.SetState(new ConcreteStateA(context));
        }
    }
    public class ConcreteStateD : State
    {
        public ConcreteStateD(Context context) : base(context)
        { }

        public override void Handle(string value)
        {
            Debug.Log("ConcreteStateC.Handle");
            if (value == "乐")
                context.SetState(new ConcreteStateA(context));
        }
    }

B.上下文

    public class Context
    {
        State state = null;

        public void Change(string value)
        {
            state.Handle(value);
        }

        public void SetState(State theState)
        {
            state = theState;
        }
    }

示例代码调用

    void UnitTest()
    {
        Context context = new Context();
        context.SetState(new ConcreteStateA(context));

        context.Change("喜");
        context.Change("怒");
        context.Change("哀");
        context.Change("乐");
    }

打印日志

3.2.5 写法对比:

3.2.6 模式分析:

状态模式简化了多状态切换时使用的if elseif语句,将对应的跳转条件与状态行为分别分散到不同的子类中。而且对应状态的添加和删减会更加容易,只需要定义新的子类即可。这种状态逻辑和跳转的隔离,减少了相互的依赖与干扰。对于状态的复用有一定的帮助。但也要关注状态子类的个数,避免状态因子类过多而造成调试上的困难。

3.2.7 应用场景:

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式。

3.2.8 小结:

在开发中一般会在有限状态机中看到状态模式的身影,这也是在实际开发中使用频率不多但针对性很强的设计模式。


更多设计模式详见:设计模式全家桶

发表评论