设计模式:状态模式

一、引子 

    状态模式自身结构非常简单——前面刚刚介绍了几个结构比较简单的设计模式,和他们 

一样,状态模式在具体实现上留下了可变换的余地。我前面已经介绍过它的孪生兄妹策略模 

式了,大家可以两者比较着阅读。本文将会讨论两者的区别。 

二、定义与结构 

    GOF 《设计模式》中给状态模式下的定义为:允许一个对象在其内部状态改变时改变它 

的行为。这个对象看起来似乎修改了它的类。看起来,状态模式好像是神通广大——居然能 

够“修改自身的类” ! 

    能够让程序根据不同的外部情况来做出不同的响应,最直接的方法就是在程序中将这些 

可能发生的外部情况全部考虑到,使用if   else  语句来进行代码响应选择。但是这种方法对 

于复杂一点的状态判断,就会显得杂乱无章,容易产生错误;而且增加一个新的状态将会带 

来大量的修改。这个时候“能够修改自身”的状态模式的引入也许是个不错的主意。 

    状态模式可以有效的替换充满在程序中的if   else 语句:将不同条件下的行为封装在一 

个类里面,再给这些类一个统一的父类来约束他们。来看一下状态模式的角色组成吧: 

1)  使用环境(Context)角色:客户程序是通过它来满足自己的需求。它定义了客户程序 

    需要的接口;并且维护一个具体状态角色的实例,这个实例来决定当前的状态。 

2)  状态(State)角色:定义一个接口以封装与使用环境角色的一个特定状态相关的行为。 

3)  具体状态(Concrete State)角色:实现状态角色定义的接口。 

    类图如下,结构非常简单也与策略模式非常相似。 

               Context 

               request()                State 

                                        handle() 

                         ConcreteSate1         ConcreteSate2 

                         handle()              handle() 

三、实现 

    由于状态模式结构非常简单,所以在这里罗列一些反映状态模式实现结构的代码没有什 

么太大的作用。如果你有兴趣的话可以按照上面类图来编写一下。 

    在引子中已经提到,状态模式在具体实现上存在不同的方案。因此这里重点就这些不同 

的实现方式进行介绍和讨论。 

    首先,实现时是否将状态角色、具体状态角色暴露给客户程序?按照GOF 的建议是不 

希望将状态角色暴露给客户程序的,与客户程序打交道的仅仅是使用环境角色,客户是不知 

道系统是怎么实现的,更不关心什么有几个具体状态。但是当使用环境角色中的初始状态紧 

紧依赖于客户程序时,适乎暴露是在所难免的——这就与策略模式异常相似了! 

    具体状态角色中的行为一般是与使用环境角色密切相关的。因此这里便有了一个小细 

节:我们把使用环境角色作为参数传递进入具体状态角色后,是在具体状态角色中来实现状 

态响应行为;还是仅仅调用在使用环境角色中已经实现了的方法?由于这些行为往往与使用 

环境角色相关,所以按照《重构》一书的“指导”——后一种实现方法是比较地道的。 

    从定义可知,状态模式是要应对状态转换的。那么状态的转换在哪里定义呢?你可以选 

择在使用环境角色的代码中来表现出来,当然这便意味着状态转变的规则就固定下来了。 

GOF  还给出了另外一种稍微灵活一点的实现方式:在每一个具体状态角色中来指定后续状 

态以及何时进行转换。 

    其实在java  强大的反射机制的支持下,我们还可以将状态的转换做的更加灵活——我 

们可以将状态转换的规则写在.xml 等等的配置文件里面甚至是数据库中,我们姑且叫做状 

态转换表。进行转换前,根据状态转换表来读取下一个状态,然后利用反射获得具体的状态 

对象……。哈哈,看起来很不错的样子,只是效率可能低一些——当然在企业应用中这应该 

不是最重要的。 

    状态模式已经被我们想象着“实现”了一番。那么状态模式的引入会给我们的程序带来哪 

些优势呢?前面我们已经说过:状态模式的引入免除了代码中复杂而庸长的逻辑判断语句。 

而且具体状态角色将具体状态和它对应的行为封装了起来,这使得增加一种新的状态变得简 

单一些。而且如果设计合理得话,具体状态角色可以被重用(和策略模式一样,可以考虑使 

用享元模式来实现)。 

    使用状态模式也会带来一些问题。每个状态对应一个具体的状态类,使得整体分散,逻 

辑不太清晰。当然对于一个状态非常多的系统,状态模式带来的优点还是大于它的缺点的。 

    由上面的分析就可以很明确的知道什么时候该使用状态模式了。下面是GOF 在《设计 

模式》中给出的状态模式的适用情况: 

    1)  一个对象的行为取决于它的状态,  并且它必须在运行时刻根据状态改变它的行为。 

    2)  一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。 

983747e9adab765c945ff13683d93e79.png

四、状态VS 策略 

    仔细对比状态模式和策略模式,难免会产生疑问:这两个明明是一个东西嘛!下面我们 

就来分析下两者区别。 

    首先我要声明,在实际应用中只要能够使得你的代码灵活漂亮起来,何必计较这些方方 

面面的差别呢? 

    Brandon Goldfedder 在《模式的乐趣》里是怎么说的:“strategy 模式在结构上与state

模式非常相似,但是在概念上,他们的目的差异非常大。区分这两个模式的关键是看行为是 

由状态驱动还是由一组算法驱动,这条规则似乎有点随意,但是在判断时还是需要考虑它。 

通常,State  模式的“状态”是在对象内部的,Strategy  模式的“策略”可以在对象外部,不过 

这也不是一条严格、可靠的规则。” 

    我很同意Brandon   Goldfedder 的观点。这两个模式的划分,就在于使用的目的是不同 

的——策略模式用来处理算法变化,而状态模式则是处理状态变化(好玄乎阿)。 

    策略模式中,算法是否变化完全是由客户程序开决定的,而且往往一次只能选择一种算 

法,不存在算法中途发生变化的情况。从《深入浅出策略模式》中的例子可以很好的看出。 

    而状态模式如定义中所言,在它的生命周期中存在着状态的转变和行为得更改,而且状 

态变化是一个线形的整体;对于客户程序来言,这种状态变化往往是透明的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297686.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Google Chrome 总提示flash插件过期,用命令行模式解决

目标那改成:"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --args --allow-outdated-plugins chrome老提示插件已被阻止: chrome://plugins/ 进入插件 选择始终允许转载于:https://www.cnblogs.com/as3lib/p/4396418.html

Windows下的gcc/gc++编译环境配置

最近有很多算法设计的网络大赛,其中大部分的C/C都是采用Linux下的GCC/G编译器。配置GCC编译器大概有这几种途径:装Linux系统、装Linux虚拟机或者在Windows环境下模拟Linux编译环境。这里谈谈有关Windows下模拟Linux编译环境的方法。 说到Windows下模拟Li…

程序员苦逼了6年,选择在街边做鸭......

1 从入门到转行可太真实了▼2 干干巴巴,麻麻赖赖给我盘!▼3 这位高人一看就是本科蓝翔,新东方硕博连读▼4 主要还是男人比较自信▼5 逻辑清晰,思维缜密▼6 妈妈,我就想听好听的▼7 如过全网都没有广告说不定会有…

Resharper 和 Rider 的奇淫技巧,你知道多少?

.NET 开发中最令人印象深刻的生产力工具之一是ReSharper[1]。每次发布时,我都对它的功能感到震惊。不要误会我的意思,我喜欢 Visual Studio,而且它也变得越来越好。但每当我认为 Visual Studio 迎头赶上时,我就会发现一些令人惊叹…

流量节省模式 Android,这三种方法让你节省更多手机上网流量

大多数手机用户应该都知道最基本的流量管理方式——没有Wi-Fi可用时就不看视频、不玩在线游戏、或者下载大型应用——除非你拥有不限流量套餐。但如果你在使用流量时已经很节约,但每个月的用量依然会超出流量套餐,那下面这三种方法应该可以确保你不会浪费…

PS比狠大赛!看看谁家的照片更丑!

全世界只有3.14 % 的人关注了爆炸吧知识最近在网上看到一个“丑照片挑战”本来以为就是丑吧结果一看惊了张张都是文艺大片范儿一点都不丑至于为什么叫丑照片挑战赛来看看他们的实拍背景就知道了比如第一张小姐姐的酷拽镜头靠的竟然是餐桌上这盆小绿植第二张的帅气小哥哈哈哈对不…

.NET 6 数组拷贝性能对比

本文来对比多个不同的方法进行数组拷贝,和测试其性能测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信。在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试。详细请看 C# 标准性能测试拷贝某个数组的从…

python win32ui选取文件夹_最全 Python 算法实现资源汇总!

整理 | Rachel责编 | Jane出品 | Python大本营(ID:pythonnews)【导语】数据结构与算法是所有人都要学习的基础课程,自己写算法的过程可以帮助我们更好地理解算法思路,不要轻视每一个算法,一些虽然看似容易,但可能有很多…

兄弟,就你这智商就别出轨了吧?

1 这智商就别出轨了吧(没有聪明人就能出轨的意思)▼2 “俗话说得好”上一句是什么?▼3 这是什么诡异的老年运动?▼4 搞不懂时尚趋势在哪里.....▼5 聚餐的时候千万别拿着包去厕所▼6 一看就会一学就废▼7 聪明的狗子能有多…

requestmapping注解访问404_【框架】127:几个非常重要的注解

今天是刘小爱自学Java的第127天。感谢你的观看,谢谢你。今天的知识点有点多,有点记不过来了。学习内容安排如下:使用注解优化昨天写的springMVC入门程序。映射路径各种风格的学习,也就对应了注解RequestMapping中的参数。各种类型…

Dapr + .NET Core实战(二) 服务调用

服务调用是什么在分布式应用程序中的服务之间进行调用会涉及到许多挑战。例如:维护其他服务的地址。如何安全地调用服务。在发生短暂的 暂时性错误 时如何处理重试。分布式应用程序调用链路追踪。服务调用构建块通过使用 Dapr 挎斗作为服务的 反向代理 来解决这些难…

第五周项目2-对象作为数据成员

回想Engineer类的数据成员,有眼镜、背包等。某Engineer的眼镜、背包,是Glass、Bag类的对象。类中的数据成员,其类型可以是简单类型,也可以是类。通过这种方式,将某些类组合到另外的类中,当作其中的一个“部…

谷歌排名第一的编程语言,死磕它这两点,小白也能学的会!不信你看!

全世界只有3.14 % 的人关注了爆炸吧知识谷歌排名第一的编程语言时什么?毫无疑问:肯定是 Python。也难怪,作为大数据时代和人工智能时代的必备语言,Python 的优点太多了,语言简洁、易学、开发效率高、可移植性强......另…

android主动显示流程,Activity加载显示基本流程

本文章是基于Android源码6.0讲解Activity加载显示基本流程首先上一张图给大家一个直观的了解首先一个布局页面的加载是在Activity中的setContentView(R.layout.res)开始;我们就从Acitvity源码中的setContentView方法入手public void setContentView(LayoutRes int layoutResID)…

VIM之Project 项目管理工具

VIM是Linux和Unix下常用的文本编辑工具,在编写代码和阅读代码中经常使用。但VIM进行代码项目管理时,没有IDE集成开发工具方便,现在提供一个VIM插件Project,可以对代码项目进行简单的集中管理一、 下载安装1、 在 Vim 网站上下载最…

WPF DataGrid 通过自定义表头模拟首行固定

WPF DataGrid 通过自定义表头模拟首行固定独立观察员 2021 年 9 月 25 日最近工作中要在 WPF 中做个表格,自然首选就是 DataGrid 控件了。问题是,UI 设计的表格是在首行有一个新增按钮,那一行样式和其它数据行是一样的,就在表头下…

python和C语言分别实现插入排序

python语言代码:代码1 defInsertSort(numbers,n):2 fori inrange(1,n):3 j i-14 tem numbers[i]5 whilenumbers[j]>tem andj>0:6 numbers[j1] numbers[j]7 j -18 else:9 numbers[j1] tem10 print"Onthe sort:",numbers11 12 a [9,8,7,6,5,4,3,2,1,0…

Windows用户安全小技巧

本文适用于具有管理员用户和标准用户的所有Windows系统,如Windows 2000以上的操作系统,UAC是Windows Vista以上版本的具有功能。新安装的Windows系统或者新购买的含有Windows系统计算机一开始都需要安装许多软件并需要设置较多的含有Windows安全或用户控…

从网恋到失恋只需要一秒...

1 原来放下一个人如此简单...▼2 而且到现在衣服都没找到▼3 这东西叫糖醋液,实验室比例是:糖:醋:酒:水1:2:3:4▼4 老师:这孩子真有原则▼5 呵,绝交吧▼…

大前端快闪:package.json文件知多少?

最近在公司某项目参与了一些前端工作,作为后端抠脚大汉,改点前端细节磕磕绊绊,改点大前端、工程化、HTTP交互倒也还能做到柳暗花明。于是打算用后端程序猿的视角记录一些{大前端}的知识快闪,也算是帮助读者构建完整的全栈技能体系…