04、状态模式(State)

一、概念:

当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。【DP】

二、作用:

状态模式的主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。吧状态的判断逻辑转移到表示不同状态的一系列当中,

可以把复杂的判断逻辑简化。当然如果这个状态的判断很简单,那么就没必要用“状态模式”了,千万注意不要为了设计模式而去用设计模式。

三、通俗的概念理解:

就是为了消除庞大的条件分支语句。当一个对象的行为取决于他的状态,并且他必须在运行时刻根据状态改变他的行为时,就可以考虑使用状态模式了。

四、状态模式类图;

                                                                                        

五、对概念的理解和针对类图进行代码的开展

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace State
{
    //State类,抽象状态类,定义一个接口一封装与Context的一个特定状态相关的行为
    public abstract class State
    {
        public abstract void Handle(Context context);
    }

    //ConcreteState类,具体状态类,每一个子类实现一个与Context的一个状态相关的行为
    public class ConcreteStateA : State
    {
        public override void Handle(Context context)
        {
            context.State = new ConcreteStateB();       //设置ConcreStateA的下一状态是ConcreStateB
        }
    }

    public class ConcreteStateB : State
    {
        public override void Handle(Context context)
        {
            context.State = new ConcreteStateA();  //设置ConcreStateB的下一状态是ConcreStateA
        }
    }

    //Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
    public class Context
    {
        private State state;
        public State State
        {
            get { return state; }
            set
            {
                state = value;
                Console.WriteLine("当前状态:" + state.GetType().Name);
            }
        }

        public Context(State state)                //定义Context的初始状态
        {
            this.state = state;
        }

        public void Request()
        {
            state.Handle(this);             //对请求做处理,并设置下一状态
        }

    }

    class Program
    {
        //客户端代码;
        static void Main(string[] args)
        {
            Context context = new Context(new ConcreteStateA());   //设置Context的初始状态为ConcreStateA

            context.Request();
            context.Request();
            context.Request();
            context.Request();
            Console.ReadKey();

        }
    }
}

 结果显示

                              

六、接下啦就是对概念进行实例的操作了,概念记得再熟,也不如实战一把

这里就是以程序员的加班来进行案例的解释了,对一天的工作时间与下班来进行一个状态的切换。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test_02
{

    //抽象的状态
    public abstract class State
    {
        public abstract void WriteProgram(Work work);
    }

    //上午的工作状态
    public class ForenoonState : State
    {
        public override void WriteProgram(Work work)
        {
            if (work.Hour < 12)
            {
                Console.WriteLine("当前时间:" + work.Hour + "点,上午工作,精神还行");
            }
            else  //否则,超过12点进行状态的切换
            {
                work.SetState(new NoonState());
                work.WriteProgram();
            }
        }
    }

    //中午的工作状态
    public class NoonState : State
    {
        public override void WriteProgram(Work work)
        {
            if (work.Hour < 13)
            {
                Console.WriteLine("当前时间:" + work.Hour + "点,中午,饿了,犯困");
            }
            else //转到下午的工作状态
            {
                work.SetState(new AfternoonState());
                work.WriteProgram();
            }


        }
    }

    public class AfternoonState : State
    {
        public override void WriteProgram(Work work)
        {
            if (work.Hour < 17)
            {
                Console.WriteLine("当前时间:" + work.Hour + "点,下午状态还不错,继续努力");
            }
            else//否则,转为傍晚的工作状态
            {
                work.SetState(new EveningState());
                work.WriteProgram();
            }

        }
    }
    //晚间工作状态
    public class EveningState : State
    {
        public override void WriteProgram(Work work)
        {
            if (work.Finish == true)      //当工作完成了,则转入下班的装态
            {
                work.SetState(new RestState());
                work.WriteProgram();
            }
            else
            {
                if (work.Hour < 21)
                {
                    Console.WriteLine("当前时间:" + work.Hour + "点,加班哦,疲累至极");
                }
                else                //当时间超过21点则转入睡觉的状态
                {
                    work.SetState(new SleepState());
                    work.WriteProgram();
                }
            }
        }
    }
    //睡眠状态
    public class SleepState : State
    {
        public override void WriteProgram(Work work)
        {
            Console.WriteLine("当前时间:" + work.Hour + "点,已经撑不住了,睡着了");
        }
    }

    //下班休息状态
    public class RestState : State
    {
        public override void WriteProgram(Work work)
        {
            Console.WriteLine("当前时间:" + work.Hour + "点,下吧回家休息了");
        }
    }

    //工作类
    public class Work
    {
        private State current;
        public Work()
        {
            current = new ForenoonState();//工作的初始状态为上午工作状太,9点开始工作
        }
        private double hour;    //属性,状态切换的依据

        public double Hour
        {
            get { return hour; }
            set
            {
                hour = value;
            }
        }

        private bool finish = false;        //任务完成标志,是否能下班的标志

        public bool Finish
        {
            get { return finish; }
            set { finish = value; }
        }

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

        public void WriteProgram()
        {
            current.WriteProgram(this);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Work work = new Work();
            work.Hour = 19;
            work.WriteProgram();
            Console.ReadKey();
        }
    }
}

七、总结:

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

例如可以在角色的AI切换的时候使用,在游戏界面的登录界面以及其他界面的切换中使用,

八:扩充:

  在写代码的时候,一定要避免在一个类中的方法过于太长了的情况发生,看起来也是不太舒服的!

 

                                                                                                                   2017-12-14 00:27:06

原文地址:https://www.cnblogs.com/zhh19981104/p/8035691.html