转自:设计模式是什么鬼(状态)

状态State,指某事物所处的状况或形态,比如水的三态,零下会变成固态冰,常温会是液态水,100℃会蒸发成气态的水蒸气。

在这个地球生态系统中,水的总量并不会增加,也不会减少,只是随着温度的变化其分子间发生了稀松紧密的变化罢了,于是便有了不同的行为,比如流动、凝固、或是蒸腾,但对于其本质H2O分子对象并没有任何变化,变化的,只是其形态。

当然,事物的状态都是不同的,有的多有的少。物质基本三态,人的精神状态更是非常复杂多变的,喜怒哀乐,五味杂陈。更有趣的是,对于某些患有严重的精神分裂的病人来说,其精神状态更是变化无常,有些竟可以扮演几十种角色,随时间或境遇切换,一会变成精明聪颖的律师,一会是懦弱的失败者总是要自杀,一个境遇触发又是愤怒的杀人暴徒,这人格切换速度,丧心病狂到令人发指。

言归正传,依旧老惯例,我们还是用极简主义阴阳二态来做药引子,想必每个人家里都有开关吧,其暴露出两个UI可操作接口(对接你的手指):开,关。很简单吧?

好我们来分析一下,首先得定义一个类吧,就叫它:Switcher好了,对外暴露两个方法:switchOn()以及switchOff(),以便用户调用,OK,开始我们的代码。

 public class Switcher {//false代表关,true代表开private boolean state = false;//初始状态是关public void switchOn(){state = !state;System.out.println("OK...灯亮");}public void switchOff(){state = !state;System.out.println("OK...灯灭");}
}

完成了?没问题了?这也太简单了吧?当然说这个没问题是在前端UI壳子设计精妙的前提下,但这并不能代表我们的程序设计没问题。试想如果UI可以重复调用开或者关会出现什么情况?状态乱套了!这个设计是非常不可靠的,我们不能因为表面设计上的完美就忽略了后端代码功能的逻辑正确性,表里不一。这就是为什么我们做应用时不但要做好前端校验(用户体验),更要保证后端校验(功能正确性)不可缺失。

想明白了的话我们继续,现在改一下我们之前的设计,这里一定要加入针对当前状态的条件判断,也就是说,开的状态不能再开,关的状态不能再关!

 public class Switcher {//false代表关,true代表开boolean state = false;//初始状态是关public void switchOn(){if(state == false){//当前是关状态state = true;System.out.println("OK...灯亮");}else{//当前是开状态System.out.println("WARN!!!通电状态无需再开");}}public void switchOff(){if(state == true){//当前是开状态state = false;System.out.println("OK...灯灭");}else{//当前是关状态System.out.println("WARN!!!断电状态无需再关");}}
}

我们可以看到这里加入了逻辑判断,如果重复开或者重复关的话是会告警的,当然这里也可以抛异常出去,我们就不搞那么复杂化了。那对于这样的设计没有问题吧?很显然,逻辑上是跑的通的,写个Client类测试一下。

public class Client {public static void main(String[] args) {Switcher s = new Switcher();s.switchOff();//WARN!!!断电状态无需再关s.switchOn();//OK...灯亮s.switchOff();//OK...灯灭s.switchOn();//OK...灯亮s.switchOn();//WARN!!!通电状态无需再开}}

So far,不管熊孩子怎么开开关关都不会有问题了。可惜我还是要很遗憾地告诉你,这样的设计仍然是糟糕的。试想,如果状态不止一种,并且状态切换有及其复杂的逻辑,例如,之前那个精神病患者,或者汽车的自动挡。

如果按照这种设计的结果会是?码农一定要有一种打破砂锅问到底的精神,不撞南墙不回头,Lu起袖子马上干!我们写一小段代码来看看先。

 public class Car {//0:Park驻车档,1:Reverse倒退挡,//2:Neutral空挡,3:Drive前进档。String state = "P";//初始状态是P档public void push(){//向上推档杆switch (state) {case "P"://驻车档状态System.out.println("WARN!!!到头了推不动了!");break;case "R"://倒挡状态state = "P";System.out.println("OK...切P档");break;case "N"://空档状态System.out.println("OK...切R档");break;case "D"://前进档状态System.out.println("OK...切N档");break;default:break;}}public void pull(){//向下拉档杆//这里省略,逻辑同上类似}
}

不用多说什么了吧,这个是在作死了,那一大堆逻辑判断写在宿主类里会越来越像蜘蛛网!我们必须想方设法把这个设计给模块化,把状态模块给独立出来!还记得我们曾经讲过的设计模式是什么鬼(策略)吧,算法策略被抽离出来,这里举一反三,把状态也给抽离出来,好了办法有了,我们忘掉自动挡,继续用我们大道至简的开关例子。

public interface State {public void switchOn(Switcher switcher);//开public void switchOff(Switcher switcher);//关
}

以上我们首先了定义一个状态State接口,两个方法开与关,注意这里与策略模式不同的是,我们为了与宿主Switcher对接所以把它作为参数传入。然后是开状态与关状态的实现。

 public class On implements State {@Overridepublic void switchOn(Switcher switcher) {System.out.println("WARN!!!通电状态无需再开");return;}@Overridepublic void switchOff(Switcher switcher) {switcher.setState(new Off());System.out.println("OK...灯灭");}
}
 public class Off implements State {@Overridepublic void switchOn(Switcher switcher) {switcher.setState(new On());System.out.println("OK...灯亮");}@Overridepublic void switchOff(Switcher switcher) {System.out.println("WARN!!!断电状态无需再关");return;}
}

显而易见,注意看第10行代码,开状态不能做开行为,只告警并返回,关状态反之亦然。而第4行代码则是合法的行为,所以可以进行状态切换并实施相应行为,也就是说,开状态可关,关状态可开。注意这里是把宿主对象传入进来用于切换其当前状态,亦或是调用宿主的具体功能方法(这里省略用打印输出代替),比如宿主里的一盏灯提供的方法。

至此,一切看起来非常优雅,我们已经成功的将状态从宿主中抽离了,最后再来看宿主开关类是什么样子。

 public class Switcher {//开关的初始状态设置为“关”private State state = new Off();public State getState() {return state;}public void setState(State state) {this.state = state;}public void switchOn(){state.switchOn(this);//这里调用的是当前状态的开方法}public void switchOff(){state.switchOff(this);//这里调用的是当前状态的关方法}
}

甚至我们还可以给里面加一盏灯,像之前我们提到的那样,在State状态接口实现里去调用。

public class Switcher {//...之上代码略...private Lamp lamp;public void lampOn(){lamp.on();}public void lampOff(){lamp.off();}
}

看明白了吧?是不是很像策略模式?其实它就是策略的一个变种,只不过状态模式会更好的根据当前的状态去实施不同的行为,并且自主切换到另一个正确的状态,开变关,关变开。就好似电梯(虽然是嵌入式面向过程,这里只是举例),用户根本无法随意强制更改其状态以及行为,你让它上,它不一定马上就能上,否则会造成事故。电梯内部封装了多个状态以及对应的逻辑产生不同的行为,它会根据当前状态去自我调整并实施最优方案,以达到安全、高效的目的,这才是可靠的设计。

这些例子都很简单吧?确实很简单,但也不简单,例子本身简单,理解并不简单,所以大家一定要多分析思考,举一反三,最终才能融汇贯通,自由运用。光说不练是不行的,理论指导实践,实践加强理论,建议大家亲自去写一下上面的汽车自动挡例子。

设计模式是什么鬼(状态)相关推荐

  1. JAVA设计模式什么鬼(状态)——作者:凸凹里歐

    状态State,指某事物所处的状况或形态,比如水的三态,零下会变成固态冰,常温会是液态水,100℃会蒸发成气态的水蒸气. 在这个地球生态系统中,水的总量并不会增加,也不会减少,只是随着温度的变化其分子 ...

  2. 设计模式示例_状态设计模式示例

    设计模式示例 本文是我们名为" Java设计模式 "的学院课程的一部分. 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们. 您将了解模式如此重要的原因 ...

  3. 设计模式学习笔记——状态(State)模式框架

    设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...

  4. 设计模式是什么鬼(模板方法)

    转自:设计模式是什么鬼(模板方法) 面向对象,是对事物属性与行为的封装,方法,指的就是行为.模板方法,显而易见是说某个方法充当了模板的作用,其充分利用了抽象类虚实结合的特性,虚部抽象预留,实部固定延续 ...

  5. 设计模式是什么鬼(原型)

    转自:设计模式是什么鬼(原型) 原型(Prototype)是什么意思?工业生产中通常是指在量产之前研发出的概念实现,如果可行性满足即可参照原型进行量产.有人说了,那不就是印章?其实这并不怎么贴切,印章 ...

  6. 设计模式是什么鬼(单例)

    转自:设计模式是什么鬼(单例) 之前我们讲过面向对象以及封装.继承.多态三大特性,底子打好了那我们就把设计模式一个个拆开来看看到底都是神些什么鬼,我们先从简单的单例说起吧.单例,顾名思义,整个系统其实 ...

  7. c语言lr分析器的设计与实现_Python3设计模式四 :状态模式

    状态(state)模式在实现上类似于策略模式,但是它们的目标非常的不同.状态模式呈现的是一个状态转换系统:系统中的对象处在一个特定的状态当中,经过某些操作之后可以抵达另外的状态. 为了实现这一目标,需 ...

  8. 【游戏设计模式】之三 状态模式、有限状态机

    转载自:https://blog.csdn.net/poem_qianmo/article/details/52824776 游戏开发过程中,各种游戏状态的切换无处不在.但很多时候,简单粗暴的if e ...

  9. 【游戏设计模式】之三 状态模式、有限状态机 Unity版本实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/52824776 作者:毛星云(浅 ...

最新文章

  1. Unity3D第三人称摄像机控制脚本
  2. 原生、无依赖的web弹层组件——HLayer.js
  3. b区计算机考研招不满的大学,b区考研招不满的大学,适合调剂的学校有哪些
  4. BZOJ2877 NOI2012魔幻棋盘(二维线段树)
  5. Windows安装Python3
  6. ML之ME/LF:机器学习中常见模型评估指标/损失函数(LiR损失、L1损失、L2损失、Logistic损失)求梯度/求导、案例应用之详细攻略
  7. H5js的一些好玩的东西
  8. spring boot部署到tomcat
  9. HTTP系列之:HTTP中的cookies
  10. 【渝粤题库】陕西师范大学202071 统计学 作业(专升本、高起本)
  11. VScode 透明背景设置
  12. iOS定位服务与地图开发(6)---使用程序外地图之调用谷歌Web地图
  13. 洛谷 [P2859] 摊位预定
  14. 20140711 loop-II 调和数列
  15. F1, 中位数,四分位距IQR等指标的统计检验
  16. angularJs监控页面加载完毕
  17. GitHub哔哩哔哩(bilibili)高清视频下载
  18. Apache安全漏洞
  19. redis—redis概述
  20. threejs-纹理贴图

热门文章

  1. 魅族官宣好消息:魅族16s Pro暮光森林终于要来了
  2. 小红书发布声明:已对站内内容启动全面排查、整改
  3. 月费10元起!中国移动推年轻人的第一张5G元素电话卡
  4. 换手机的等等!什么时候能用上1000元级5G手机?中国移动公布时间表
  5. 谷歌看下!罗永浩谈谷歌砍掉平板线 :主要是因为软件太烂
  6. 相机翻转设计的华硕旗舰ZenFone 6固件更新:新增“超级夜间模式”
  7. 放弃第三方?苹果正自研iPhone调制解调器芯片
  8. 读芯术python答案_你爱 “Python”的身体,还是“R”的灵魂?
  9. windows下获取IP和MAC地址
  10. 完成一个YUV文件播放器