天天看点

设计模式读书笔记-----状态模式

      在介绍状态模式之前,我们先来看这样一个实例:你公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上。下图是他们系统的主要工作(够简单)。

设计模式读书笔记-----状态模式

      当你第一眼看到这个系统的时候你就看出来了这是一个状态图,每个框框都代表了房间的状态,箭头表示房间状态的转换。分析如下:房间有三个状态:空闲、已预订、已入住,状态与状态之间可以根据客户的动作来进行转换。定义每个状态的值。

      通过客户的动作将每个状态整合起来,对于这个“最简单”的方式肯定是if…else if…else啦!所以这里我们就通过动作将所有的状态全面整合起来。分析得这里有四个动作:预订、入住、退订、退房。如下:

      对于上面的代码你是否满意呢?满意那么你就没有必要往下看了,不满意我们接着讲。

      正当你完成这个“复杂”if..else if …else时(我都写了一会儿),你客户说,我们需要将某些房间保留下来以作为备用(standbyState),于是你发现你悲剧了,因为你发现你要在所有的操作里都要判断该房间是否为备用房间。当你老大经过你身边的时候发现你正在纠结怎么改的时候,你老大就问你为什么不换一个角度思考以状态为原子来改变它的行为,而不是通过行为来改变状态呢?于是你就学到了状态模式。

      在很多情况下,一个对象的行为取决于它的一个或多个变化的属性,这些属性我们称之为状态,这个对象称之为状态对象。对于状态对象而已,它的行为依赖于它的状态,比如你要预订房间,那么只有当该房间为空闲时你才能预订,你想入住该房间也只有当你预订了该房间或者该房间为空闲时。对于这样的一个对象,当它在于外部事件产生互动的时候,其内部状态就会发生改变,从而使得他的行为也随之发生改变。

      那么何为状态模式呢?所谓状态模式就是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

      下图为状态模式的UML图。

设计模式读书笔记-----状态模式

      状态模式包含如下角色:

         Context: 环境类。可以包括一些内部状态。

         State: 抽象状态类。State定义了一个所有具体状态的共同接口,任何状态都实现这个相同的接口,这样一来,状态之间就可以互相转换了。

         ConcreteState: 具体状态类。具体状态类,用于处理来自Context的请求,每一个ConcreteState都提供了它对自己请求的实现,所以,当Context改变状态时行为也会跟着改变。

      依然是上面那个酒店的实例。对于该实例的UML图如下:

设计模式读书笔记-----状态模式

      首先是状态接口:State

      然后是房间类

      然后是3个状态类,这个三个状态分别对于这:空闲、预订、入住。其中空闲可以完成预订和入住两个动作,预订可以完成入住和退订两个动作,入住可以退房。

      最后是测试类

      运行结果

设计模式读书笔记-----状态模式

      1、封装了转换规则。

      2、枚举可能的状态,在枚举状态之前需要确定状态种类。

      3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

      4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

      5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

      1、状态模式的使用必然会增加系统类和对象的个数。

      2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

      3、状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

     1、对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。

     2、代码中包含大量与对象状态有关的条件语句

     1、状态模式允许一个对象基于内部状态而拥有不同的行为。

     2、Context会将行为委托给当前状态对象。

     3、状态模式对“开闭原则”支持不是很好。

PS:如果你觉得文章对你有所帮助,别忘了推荐或者分享,因为有你的支持,才是我续写下篇的动力和源泉!

作者:chenssy。一个专注于【死磕 Java】系列创作的男人

出处:https://www.cnblogs.com/chenssy/p/3280212.html

作者个人网站:https://www.cmsblogs.com/。专注于 Java 优质系列文章分享,提供一站式 Java 学习资料

目前死磕系列包括:

    1. 【死磕 Java 并发】:https://www.cmsblogs.com/category/1391296887813967872(已完成)

    2.【死磕 Spring 之 IOC】:https://www.cmsblogs.com/category/1391374860344758272(已完成)

    3.【死磕 Redis】:https://www.cmsblogs.com/category/1391389927996002304(已完成)

    4.【死磕 Java 基础】:https://www.cmsblogs.com/category/1411518540095295488

    5.【死磕 NIO】:https://www.cmsblogs.com/article/1435620402348036096

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。