• c#之状态者模式


    状态者模式

    一:状态者模式的定义

    当一个对象的内在的状态改变时允许改变其行为,这个对象看起来像是改变了其类,状态者模式中主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转换到表示不同状态的一系列类当中,可以把复杂的判断逻辑简单化。如果这个状态的判断很简单,那就没有必须用“状态模式”了。

    二:案例的展示:

    就比如说我们拿上班的状态来表示:上午的状态好,中午想睡觉,下午逐渐恢复,加班苦煎熬。其实就是一种状态的改变,不同的时间会有不同的状态。这个时候我们马上就能想到在一个方法中写一大片的if_else if 来表示了。但是我们考虑一下,这样写真的好吗?显然是不好的,这违背了我们的“开放-封闭原则”。而且一个方法过长显然是不好的。这样的话就让我们的一个类担任了太多的职责。而我们面向对象的设计就是希望做代码的责任分解。

    首先我们按照状态者模式的定义来画上结构图:

    三:状态者模式的好处与用处:

    状态模式的好处就是:将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在与某一个ConcreteState中,所以通过定义新的子类就可以很容易的增加新的状态和转换。

    说白了这样做的目的就是:为了消除庞大的条件分支语句,状态模式就是通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。

    那么我们考虑什么时候使用状态模式呢?:当一个对象的行为取决于它的状态,并且他必须在运行时刻根据状态改变它的行为的时,就可以考虑使用状态模式了。

    四:代码的使用:

    4.1:定义State类,抽象的状态类,定义一个接口以封装与Context(维护一个ConcreteState子类的实例,这个实例定义当前的状态)的一个特定状态相关的行为。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 抽象的状态
        /// </summary>
        public abstract class State
        {
            /// <summary>
            /// 抽象的方法写程序
            /// </summary>
            public abstract void WriteProgram(Work w);
        }
    }

    4.2:定义ConcreteState类,具体的状态,每一个子类实现一个与Context的一个状态相关的行为。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 上午的工作的状态
        /// </summary>
        public class ForenoonState : State
        {
            public override void WriteProgram(Work w)
            {
                if (w.Hour < 12)
                {
                    Console.WriteLine("当前的时间:{0}点上午工作,精神百倍", w.Hour);
                }
                else
                {
                    //超过12点则进入下午的工作的状态
                    w.SetState(new NoonState());
                    w.WriteProgram();
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 中午的工作的状态
        /// </summary>
        public class NoonState : State
        {
            public override void WriteProgram(Work w)
            {
                if (w.Hour < 13)
                {
                    Console.WriteLine("当前的时间:{0}点饿了,午饭 犯困 午休", w.Hour);
                }
                else
                {
                    w.SetState(new AfternoonState());
                    w.WriteProgram();
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 下午的工作的状态
        /// </summary>
        public class AfternoonState : State
        {
            public override void WriteProgram(Work w)
            {
                if (w.Hour < 17)
                {
                    Console.WriteLine("当前的时间:{0}点下午状态还不错,继续努力", w.Hour);
                }
                else
                {
                    w.SetState(new EveningState());
                    w.WriteProgram();
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 晚间的工作的状态
        /// </summary>
        public class EveningState : State
        {
            public override void WriteProgram(Work w)
            {
                if (w.Hour < 21)
                {
                    Console.WriteLine("当前的时间:{0}点加班哟,疲累至极", w.Hour);
                }
                else
                {
                    w.SetState(new SleepingState());
                    w.WriteProgram();
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 下班休息状态
        /// </summary>
        public class RestState : State
        {
            public override void WriteProgram(Work w)
            {
                Console.WriteLine("当前的时间:{0}点下班回家了", w.Hour);
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 晚间的工作的状态
        /// </summary>
        public class EveningState : State
        {
            public override void WriteProgram(Work w)
            {
                if (w.Hour < 21)
                {
                    Console.WriteLine("当前的时间:{0}点加班哟,疲累至极", w.Hour);
                }
                else
                {
                    w.SetState(new SleepingState());
                    w.WriteProgram();
                }
            }
        }
    }

    定义工作类,此时没有了过长的分支判断语句。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        /// <summary>
        /// 工作的方法
        /// </summary>
        public class Work
        {
    
            private State current;
    
            /// <summary>
            /// 构造函数的定义
            /// </summary>
            public Work()
            {
                //工作初始化为上午的工作的状态,即上午9点开始上班
                current = new ForenoonState();
            }
    
            private double _hour;
            /// <summary>
            /// 钟点的属性 状态转换的依据
            /// </summary>
            public double Hour
            {
                get { return _hour; }
                set { _hour = value; }
            }
    
            private bool _finish;
            /// <summary>
            /// “任务完成”的属性 是否能下班的依据
            /// </summary>
            public bool Finish
            {
                get { return _finish; }
                set { _finish = value; }
            }
    
            /// <summary>
            /// 状态的设置
            /// </summary>
            /// <param name="s"></param>
            public void SetState(State s)
            {
                current = s;
            }
    
            /// <summary>
            /// 写程序
            /// </summary>
            public void WriteProgram()
            {
                current.WriteProgram(this);
            }
    
        }
    }

    客户端代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 状态模式
    {
        class Program
        {
            static void Main(string[] args)
            {
                //紧急项目
              Work emergencyProjects = new Work();
                emergencyProjects.Hour = 9;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 10;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 12;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 13;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 14;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 17;
                emergencyProjects.Finish = false;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 19;
                emergencyProjects.WriteProgram();
    
                emergencyProjects.Hour = 22;
                emergencyProjects.WriteProgram();
    
                Console.ReadKey();
    
            }
        }
    }

     假如说我们在增加“员工必须在20点之前离开公司”,我们只需要增加一个“强制下班的状态”并改动一下“傍晚工作状态”类的判断就可以了。而且又不影响其他的类的代码。  

     

  • 相关阅读:
    一份详尽的 Java 问题排查工具清单,值得收藏!
    专业解决 MySQL 查询速度慢与性能差!
    马士兵对话京东T6阿里P7(薪水):月薪5万,他为何要离职?
    Java中的注解到底是如何工作的?
    一道简单的面试题,难倒各大 Java 高手!
    疯狂618,当当买书打 3 折!
    SQL才是世界上最牛逼的语言!
    程序员必须掌握的职场黑话,你知道几个?
    面试问我 Java 逃逸分析,瞬间被秒杀了。。
    redis 介绍与操作
  • 原文地址:https://www.cnblogs.com/MoRanQianXiao/p/7750853.html
Copyright © 2020-2023  润新知