状态模式

简介:

假设某人一整天的流程就是“吃饭→工作→睡觉”,并且他要严格按照这个流程来,那也就是说在吃饭状态下,他只能做跟吃饭有关的事情,而不能越界做工作或者睡觉有关的事情,这就涉及到了状态的管理。在写代码的时候,我们常常要根据当前的状态,来决定下一个状态并且确定当前状态下要做什么样的事情。一般来讲,我们会写一系列的if-else if-else if-else语句来实现,但是要是状态非常多的时候,这种代码不仅仅看起来十分长,而且看的人生理上也会有一种厌恶感并且看一点估计忘一点。导致这种臭代码的原因就是,我们一口气在一个函数里面管理了太多种的状态。于是,有人就提出了,能不能让状态自己管理自己。也就有点像我们的行政制度中自治区,我们不再统一地在一个函数里面管理N种状态,而是让某个状态管理它自己本身。

经典的状态管理模式如下图所示

image

让我来解释一下这幅图的意思,IState依赖于IContext,也就是IContext对应的实体类拥有一个IState类型的字段,在IContext类里面的Request()方法里面调用IState中的Handle方法。我们可以通过改变IContext里面的IState实体类类型来改变状态,从而实现根据不同的状态使用不同的方法。

     下面让我们来段代码说明一下。以下代码模拟数据库的连接、关闭。连接和关闭两个状态分别有两个对应的状态类与之对应。

1、首先我们还是先定义状态的接口,另外定义一个抽象类,用来表示数据库连接类。

复制代码
/// <summary>
    /// 数据库连接状态
    /// </summary>
    public interface IConnectionState
    {
        void Open();
        void Close();
        void Query();
    }
复制代码

在定义一个数据库连接对象的抽象基类

复制代码
abstract class ContextBase
    {

        private IConnectionState connectionState;

        public IConnectionState ConnectionState
        {
            get { return connectionState; }
            set { connectionState = value; }
        }

        public virtual void Open() { this.connectionState.Open(); }
        public virtual void Close() { this.connectionState.Close(); }
        public virtual void Query() { this.connectionState.Query(); }
    }
复制代码

2、我们再定义两个具体类OpenState、CloseState,实现IConnectionState接口,分别代表数据库开、关两种状态。并且在状态类内部,如OpenState类的内部规定了在Opne状态下,可以执行的操作和不能够执行的操作。

复制代码
/// <summary>
        /// 打开状态
        /// </summary>
        class OpenState : IConnectionState
        {

            public void Open()
            {
                throw new NotImplementedException("打开状态下,不能再打开数据库连接");
            }

            public void Close()
            {
                //打开状态下,可以关闭数据库连接
            }

            public void Query()
            {
                //打开状态下,可以查询
            }
        }
        /// <summary>
        /// 关闭状态
        /// </summary>
        class CloseState : IConnectionState
        {

            public void Open()
            {
                //关闭状态下可以重新打开连接
            }

            public void Close()
            {
                throw new NotImplementedException("关闭状态下,不能再关闭数据库连接");
            }

            public void Query()
            {
                throw new NotImplementedException("关闭状态下,不能查询数据库");
            }
        }
复制代码

3、下面我们用一个类来继承抽象类,并进行测试。具体的类实现方式见下方,这里只给出关键函数。

复制代码
public void ConnectionStateTest()
        {
            ContextBase target = CreateContextBase(); 
            target.ConnectionState = new OpenState();
            try
            {
                target.Open();//执行Open操作,遇到异常,不执行 Assert.IsTrue(false);
                Assert.IsTrue(false);
            }
            catch (Exception ex)
            {
                
            }
            target.Close();//在打开状态下,正常关闭,并执行Assert.IsTrue(false);
            Assert.IsTrue(false);

            target.ConnectionState = new CloseState();
            try
            {
                target.Close();
                Assert.IsTrue(false);
            }
            catch (Exception ex)
            {
            }

            target.Open();
            Assert.IsTrue(false);
        }
复制代码

从以上代码,我们可以知道,原先需要用讨厌的if-else if-else if-else管理的讨厌的长长的状态管理函数,已经被我们封装在一个个的小状态管理类里面了,并且这些状态管理类可以自己管理自己什么状态应该做什么样的事情。

  状态管理类完整代码
本文转自陈哈哈博客园博客,原文链接http://www.cnblogs.com/kissazi2/p/3285879.html如需转载请自行联系原作者

kissazi2
相关文章
|
安全 数据可视化 Java
深入理解Java多线程编程及原理解析
深入理解Java多线程编程及原理解析
162 0
|
11月前
|
JSON 算法 Java
hutool工具的简单使用
这篇文章介绍了Hutool工具库的基本使用,通过代码示例展示了如何利用Hutool进行字符串处理、文件操作、集合操作、加密解密、日期时间处理、网络请求和读取资源文件等常见任务。
370 0
hutool工具的简单使用
|
8月前
|
存储 JSON 对象存储
如何使用 Python 进行文件读写操作?
大家好,我是V哥。本文介绍Python中文件读写操作的方法,包括文件读取、写入、追加、二进制模式、JSON、CSV和Pandas模块的使用,以及对象序列化与反序列化。通过这些方法,你可以根据不同的文件类型和需求,灵活选择合适的方式进行操作。希望对正在学习Python的小伙伴们有所帮助。欢迎关注威哥爱编程,全栈路上我们并肩前行。
197 4
|
Ubuntu 物联网 Linux
性能工具之emqtt_bench快速上手
【4月更文挑战第8天】MQTT 协议是目前最适合物联网场景数据平台搭建的通信协议。基于此,BenchMark 联网场景中的 MQTT 消息采集与传递,以及如何构建一个百万级,甚至千万级 MQTT 消息平台,可以为物联网业务的企业用户提供平台架构设计参考。
537 2
性能工具之emqtt_bench快速上手
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的外卖商城平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的外卖商城平台的详细设计和实现(源码+lw+部署文档+讲解等)
|
应用服务中间件 nginx
nginx禁止未绑定域名或IP访问-全局设置
nginx禁止未绑定域名或IP访问-全局设置
381 0
|
Cloud Native Dubbo 应用服务中间件
系列征文2|后端领域主题征文开始啦!参与即有奖!
阿里云开发者社区推出“后端技术征文挑战赛”。现面向社区所有开发者征集后端领域技术文章,可以是语言框架的使用技巧,也可以是技术领域的趋势探讨,只要你有干货,那就分享出来!在活动规定时间内前往阿里云开发者社区发文,就有机会获得空气炸锅、社区积分等丰富奖励,参与即可获奖,快来参加吧!
1842 17
系列征文2|后端领域主题征文开始啦!参与即有奖!
|
XML 数据格式
进一步了解XPath
进一步了解XPath
|
Java
JVM-08垃圾收集Garbage Collection【GC常用参数】
JVM-08垃圾收集Garbage Collection【GC常用参数】
109 0
请大家配“合核酸采集 打印疫情战役 ”
请大家配“合核酸采集 打印疫情战役 ”
118 0
请大家配“合核酸采集  打印疫情战役 ”