设计模式之禅之设计模式-状态模式
一:状态模式定义
--->当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类
--->状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样
--->状态模式相对来说比较复杂,它提供了一种对物质运动的另一个观察视角,通过状态变更促使行为的变化,就类似水的状态变更一样,一碗水的初始状态是液态,通过加热转变为气态,状态的改变同时也引起体积的扩大,然后就产生了一个新的行为:鸣笛或顶起壶盖,瓦特就是这么发明蒸汽机的
二:状态模式角色
● State——抽象状态角色接口或抽象类
负责对象状态定义,并且封装环境角色以实现状态切换。
● ConcreteState——具体状态角色
每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。
● Context——环境角色
定义客户端需要的接口,并且负责具体状态的切换。
【*****】环境角色不成文的约束
● 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。
● 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
三:状态模式的应用
【1】状态模式的优点
● 结构清晰
避免了过多的switch...case或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。
● 遵循设计原则
很好地体现了开闭原则和单一职责原则,每个状态都是一个子类,你要增加状态就要增加子类,你要修改状态,你只修改一个子类就可以了。
● 封装性非常好
这也是状态模式的基本要求,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。
【2】状态模式的缺点
状态模式既然有优点,那当然有缺点了。但只有一个缺点,子类会太多,也就是类膨胀。如果一个事物有很多个状态也不稀奇,如果完全使用状态模式就会有太多的子类,不好管理,这个需要大家在项目中自己衡量。其实有很多方式可以解决这个状态问题,如在数据库中建立一个状态表,然后根据状态执行相应的操作,这个也不复杂,看大家的习惯和嗜好了。
【3】状态模式的使用场景
● 行为随状态改变而改变的场景
这也是状态模式的根本出发点,例如权限设计,人员的状态不同即使执行相同的行为结果也会不同,在这种情况下需要考虑使用状态模式。
● 条件、分支判断语句的替代者
在程序中大量使用switch语句或者if判断语句会导致程序结构不清晰,逻辑混乱,使用状态模式可以很好地避免这一问题,它通过扩展子类实现了条件的判断处理。
【4】状态模式的注意事项
状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生比较大的变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的状态最好不要超过5个
四:状态模式的案例
【1】电梯四个状态所作的固定的反应
【1】电梯的状态抽象
1 package com.yeepay.sxf.template21; 2 /** 3 * 抽象电梯状态 4 * 5 * (1)依赖:环境角色 6 * (2)不同状态下的行为 7 * @author sxf 8 * 9 */ 10 public abstract class LiftState { 11 12 //定义一个环境角色,也就是封装状态的变化引起功能的变化 13 protected Context context; 14 15 public void setContext(Context context){ 16 this.context=context; 17 } 18 //电梯的开启门行为 19 public abstract void open(); 20 //电梯的关闭们行为 21 public abstract void close(); 22 //电梯要能上能下,运行起来的行为 23 public abstract void run(); 24 //电梯停下来的行为 25 public abstract void stop(); 26 }
View Code
【2】环境角色
1 package com.yeepay.sxf.template21; 2 /** 3 * 环境类(上下文类) 4 * (1)依赖:电梯的状态 5 * (2)同时具有电梯不同状态的行为,类似代理 6 * @author sxf 7 * 8 */ 9 public class Context { 10 11 //定义出电梯所有的状态 12 public final static OpenningState openningState=new OpenningState(); 13 public final static ClosingState closingState=new ClosingState(); 14 public final static RunningState runningState=new RunningState(); 15 public final static StoppingState stoppingState=new StoppingState(); 16 17 //定义一个当前的电梯状态 18 private LiftState liftState; 19 20 public LiftState getLiftState(){ 21 return this.liftState; 22 } 23 24 public void setLiftState(LiftState liftState){ 25 this.liftState=liftState; 26 this.liftState.setContext(this); 27 } 28 //开启电梯门 29 public void open(){ 30 this.liftState.open(); 31 } 32 //关闭电梯门 33 public void close(){ 34 this.liftState.close(); 35 } 36 //停止电梯 37 public void stop(){ 38 this.liftState.stop(); 39 } 40 //运行电梯 41 public void run(){ 42 this.liftState.run(); 43 } 44 }
View Code
【3】电梯开启状态的实现类
1 package com.yeepay.sxf.template21; 2 /** 3 * 电梯开启状态 4 * @author sxf 5 * 6 */ 7 public class OpenningState extends LiftState { 8 9 10 //开启当然可以关闭了 11 @Override 12 public void open() { 13 System.out.println("OpenningState.open(电梯门开启......)"); 14 } 15 16 @Override 17 public void close() { 18 //修改状态 19 super.context.setLiftState(Context.closingState); 20 //动作委托为CloseState来执行 21 super.context.getLiftState().close(); 22 23 } 24 25 //电梯门若是开着,则不能运行 26 @Override 27 public void run() { 28 //do nothing; 29 } 30 //电梯门是开着,则不能让其停止 31 @Override 32 public void stop() { 33 //do nothing 34 } 35 36 37 }
View Code
【4】电梯停止状态的实现类
1 package com.yeepay.sxf.template21; 2 /** 3 * 电梯停止的行为 4 * @author sxf 5 * 6 */ 7 public class StoppingState extends LiftState { 8 9 10 11 //电梯处于停止状态是可以打开的 12 @Override 13 public void open() { 14 //将电梯的状态设置为打开 15 super.context.setLiftState(Context.openningState); 16 //执行打开的动作 17 super.context.getLiftState().open(); 18 } 19 20 //电梯处于停止状态,门本来就关着 21 @Override 22 public void close() { 23 //do nothing 24 } 25 26 //电梯处于停止状态,再次运行起来很正常 27 @Override 28 public void run() { 29 //将电梯的状态设置为运行状态 30 super.context.setLiftState(Context.runningState); 31 //执行运行动作 32 super.context.getLiftState().run(); 33 } 34 35 //停止状态要实现的行为 36 @Override 37 public void stop() { 38 System.out.println("StoppingState.stop(电梯停止了.....)"); 39 } 40 41 42 }
View Code
【5】电梯运行状态的实现类
1 package com.yeepay.sxf.template21; 2 /** 3 * 电梯运行时的状态 4 * @author sxf 5 * 6 */ 7 public class RunningState extends LiftState{ 8 9 //运行时,电梯门不允许打开。 10 @Override 11 public void open() { 12 //do nothing 13 } 14 //运行时,电梯门关闭,这是正常的。 15 @Override 16 public void close() { 17 //do nothing 18 } 19 20 //运行状态下,要实现的行为 21 @Override 22 public void run() { 23 System.out.println("RunningState.run(电梯上下运动.....)"); 24 } 25 26 //这是合理的。运行时,是可以停止的 27 @Override 28 public void stop() { 29 //将电梯的状态设置为停止状态 30 super.context.setLiftState(context.stoppingState); 31 //执行停止的动作 32 super.context.getLiftState().stop(); 33 } 34 35 36 }
View Code
【6】电梯关闭状态的实现类
1 package com.yeepay.sxf.template21; 2 /** 3 * 电梯关闭的状态 4 * @author sxf 5 * 6 */ 7 public class ClosingState extends LiftState { 8 9 10 //电梯门关了再打开 11 @Override 12 public void open() { 13 //将电梯门的状态该为打开状态 14 super.context.setLiftState(Context.openningState); 15 //执行相应的动作 16 super.context.getLiftState().open(); 17 } 18 19 //电梯们关闭,这是关闭状态要实现的动作 20 @Override 21 public void close() { 22 System.out.println("ClosingState.close(电梯门关闭.....)"); 23 } 24 25 //电梯门关了就运行,这是再正常不过了 26 @Override 27 public void run() { 28 //将电梯门的状态改为运行状态 29 super.context.setLiftState(context.runningState); 30 //执行运行状态的动作 31 super.context.getLiftState().run(); 32 } 33 34 //电梯门关着,我就不按楼层 35 @Override 36 public void stop() { 37 //将电梯门的状态改为停止状态 38 super.context.setLiftState(context.stoppingState); 39 //执行停止动作 40 super.context.getLiftState().stop(); 41 } 42 43 44 }
View Code
【4】客户端测试
1 package com.yeepay.sxf.template21; 2 /** 3 * 客户端测试 4 * @author sxf 5 * 6 */ 7 public class ClientTest { 8 9 public static void main(String[] args) { 10 //初始化上下文环境 11 Context context=new Context(); 12 //设置初始化状态 13 context.setLiftState(Context.closingState); 14 //打开门 15 context.open(); 16 //运行 17 context.run(); 18 //关闭门 19 context.close(); 20 //停止门 21 context.stop(); 22 23 } 24 }
View Code
设计模式之禅之设计模式-状态模式相关推荐
- Java设计模式之行为型:状态模式
背景: 介绍状态模式前,我们先看这样一个实例:公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上.下图是他们系统的主要工作: 当第一眼看到这个系统时你就看出这是一个状态图,每个框都代表 ...
- 设计模式与软考试题之状态模式(二)
2011年下半年软件设计师考试下午试题最后一题考查状态模式,在本试题中,命题人设计了一个具有多个状态的纸巾售卖机,真题如下: [全国计算机技术与软件专业技术资格(水平)考试 2011 年下半年 软件 ...
- 设计模式 with Python 10:状态模式
设计模式 with Python 10:状态模式 如果你接触过UML的状态图,应该会对状态图或者状态机有所了解,我们今天讨论的状态模式就是这种设计的落地方案. 和之前的讲解一样,我们从一个具体案例&q ...
- 设计模式(十五)状态模式
相关文章 设计模式系列 前言 建议在阅读本文前先阅读设计模式(十一)策略模式这篇文章,虽说状态模式和策略模式的结构几乎是相同的,但是它们所解决的问题是不同的,读完这两篇文章你就会有了答案. 1.状态模 ...
- 设计模式笔记二十一:状态模式
原文:http://www.runoob.com/design-pattern/ 少许个人理解,如有错误请指出.欢迎一起讨论.(本文多摘自原文) 在状态模式(State Pattern)中,类的行为是 ...
- 设计模式之禅【中介者模式】
真刀实枪之中介者模式 进销存管理,你管理的头大吗? 你可能会说,这有啥难的,先来幅模块示意图 从这个示意图可以看出,三个模块是相互依赖的,其中: 销售情况:销售部门要反馈情况,畅销就多采购 库存情况: ...
- 设计模式第10式:状态模式
前言 我们遇到状态机模型,常常会理不清"状态"和"行为"的关系.状态模式就是专门解决这个应用场景的,它通过改变对象内部的状态来帮助对象控制自己的行为. 正文 1 ...
- 【每天一个java设计模式(十七)】 - 状态模式
在状态模式中,类的行为是基于它的状态改变的,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示各种状态的对象和一个行为 ...
- 【设计模式】第23章·状态模式
一.状态模式概述 状态模式用于解决系统中负责对象的状态转换以及不同状态下行为的封装问题. 状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活变化. 定义: 状态模 ...
最新文章
- 微信小程序在showToast中换行并且隐藏icon
- 自己喜欢的shell终端配置
- Scala教程之:Option-Some-None
- scala akka_使用Scala,Play和Akka连接到RabbitMQ(AMQP)
- 计算机excel知识点一级,2012年计算机一级考试高分必看知识点:EXCEL
- 审计导致select * 报ORA-01435: user does not exist
- el-option传两个值_真正的释家或佛学研究者、爱好者必读文献——南朝梁·释慧皎《高僧传》...
- nslookup java_使用JAVA实现nslookup命令
- Mybatis官方文档:简介和入门
- 高等数学:第八章 多元函数的微分法及其应用(6)微分法在几何上的应用
- bugkuCTF 乌云邀请码 write up【橘小白】
- 提取windows安装盘install.wim文件修复mstsc
- Http超文本传输协议的特点
- 2012年中国本土IC设计企业排名TOP10
- windows无法连接到打印机_同事的电脑无法访问,共享打印机连接不上,问题都在这...
- web3.0 nft 是什么? nft的意义是什么?
- 计算机中模板与母版的区别,模板和模版有啥区别?
- 星象仪- 大塚爱 歌词
- 51单片机导盲手杖_超声波测距+DS18B20测温设计
- python hadoop wordcount_Hadoop之wordcount实例-MapReduce程序
热门文章
- php商品秒杀时间代码,Thinkphp5+Redis实现商品秒杀代码实例讲解
- java this 方法,使用“this”用方法(用Java)
- 想做Python自动化,这些Python常用知识你都掌握了吗?
- 插件怎么用_PPT插件怎么用?用好了10s就能给出一个动画特效,不好看不要钱
- excel工具箱_Excel工具箱15.54安装教程
- html怎么添加遮罩层,如何在浏览器窗口上添加一个遮罩层
- 怎样对php使用systemctl启动,Centos7 配置php-fpm服务到systemctl
- QTextEdit 不允许输入文字
- java实现EXcel的RC地址变成常规地址
- 在linux环境获取pcie卡信息,如何Linux下得到CPU、内存及PCI信息