状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式是一种对象行为型模式。大家着重理解对象,多种状态 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。 在状态模式结构图中包含如下几个角色: Context(环境类):环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象。 State(抽象状态类):它用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。 ConcreteState(具体状态类):它是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。 环境类实际上是真正拥有状态的对象,我们只是将环境类中与状态有关的代码提取出来封装到专门的状态类中。在状态模式结构图中,环境类Context与抽象状态类State之间存在单向关联关系,在Context中定义了一个State对象。在实际使用时,它们之间可能存在更为复杂的关系,State与Context之间可能也存在依赖或者关联关系。 在状态模式的使用过程中,一个对象的状态之间还可以进行相互转换,通常有两种实现状态转换的方式: (1) 统一由环境类来负责状态之间的转换。此时,环境类还充当了状态管理器(State Manager)角色,在环境类的业务方法中通过对某些属性值的判断实现状态转换,还可以提供一个专门的方法用于实现属性判断和状态转换。 (2)由具体状态类来负责状态之间的转换。可以在具体状态类的业务方法中判断环境类的某些属性值再根据情况为环境类设置新的状态对象,实现状态转换,同样,也可以提供一个专门的方法来负责属性值的判断和状态转换。此时,状态类与环境类之间就将存在依赖或关联关系,因为状态类需要访问环境类中的属性值。 以日常电梯为例,将电梯简单分为四种状态: 以上模式的实现,很明显不遵循设计模式的“开闭原则”,后期维护存在一定的问题。 定义抽象状态类:分别定义电梯的四种状态方法。 这里解释一下为什么 LiftState 类里面会有一个LiftContext 对象。它的作用是去调节状态的变化,它就是电梯,电梯状态肯定是针对电梯来说的,所以选择组合LiftContext 对象。 环境角色Context中,定义当前电梯的状态,处于初始化状态。同时提供外部访问方法。 运行结果: 源代码地址:https://github.com/stream-source/stream-source/tree/master/informal-essay 总结,对于状态模式,自己理解起来挺费劲的,总感觉有一个梗过不去,实际上可以将状态模式与责任链模式对比起来理解(后期责任链),就很清晰了。状态模式将对象内部状态的转化,对于外部访问并不知道。 整理的这份超全Java面试题包含: Java基础、Java异常、Spring、SpirngMVC、MyBatis、SpringBoot、SpringCloud、BIO、NIO、AIO、Netty、Tomcat、Redis、MySQL、Memcache、ElasticSearch、zookeeper、RabbitMQ、Vue、Dubbo、并发编程、Java虚拟机、TCP、Http、大数据、设计模式、Linux等 公众号Java专栏,后台回复【面试66】。即可获取!概念
状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
实践
开门、关门、运行、停止
。
如果不使用状态模式,普通if…else if …逻辑如何实现呢? /** * 普通实现结构 */ public void liftState(String state) { if (Constant.OPEN.equals(state)) { //open //close } else if (Constant.CLOSE.equals(state)) { //open //close //running //stop } else if (Constant.RUNNING.equals(state)) { //running //stop } else if (Constant.STOP.equals(state)) { //open //close //running //stop } }
下面使用状态模式如何改进。
电梯状态每个状态还都要有特定的行为,比如在开门的状态下,电梯只能关门,而不能运行;在关门状态下,电梯可以运行、开门等。用一张表来表示这个关系:
状态/动作
开门
关门
运行
停止
开门状态
O
O
X
X
关门状态
O
O
O
运行状态
X
X
O
停止状态
O
X
O
抽象状态类
public abstract class LiftState { protected LiftContext liftContext; public void setLiftContext(LiftContext liftContext){ this.liftContext = liftContext; } abstract void openState(); abstract void closeState(); abstract void runningState(); abstract void stopState(); }
下面看下具体状态实现类具体状态类
public class LiftOpen extends LiftState { @Override public void openState() { System.out.println("电梯开门..."); } @Override public void closeState() { //修改状态 super.liftContext.changeState(Constant.CLOSE); //动作委托为CloseState来执行,也就是委托给了LifeClose子类执行这个动作 super.liftContext.close(); } @Override public void runningState() { } @Override public void stopState() { //电梯开门,已经处于停止状态,无需执行其他操作 } }
public class LiftClose extends LiftState { @Override public void openState() { super.liftContext.changeState(Constant.OPEN); super.liftContext.open(); } @Override public void closeState() { System.out.println("电梯关门..."); } @Override public void runningState() { super.liftContext.changeState(Constant.RUNNING); super.liftContext.running(); } @Override public void stopState() { super.liftContext.changeState(Constant.STOP); super.liftContext.stop(); } }
public class LiftRunning extends LiftState { @Override public void openState() { } @Override public void closeState() { //电梯运行过程中,门始终处于关闭状态 } @Override public void runningState() { System.out.println("电梯运行中..."); } @Override public void stopState() { super.liftContext.changeState(Constant.STOP); super.liftContext.stop(); } }
public class LiftStop extends LiftState { @Override public void openState() { super.liftContext.changeState(Constant.OPEN); super.liftContext.open(); } @Override public void closeState() { } @Override public void runningState() { super.liftContext.changeState(Constant.RUNNING); super.liftContext.running(); } @Override public void stopState() { System.out.println("电梯停止..."); } }
环境上下文
public class LiftContext { //定义当前电梯状态 private LiftState liftState; public LiftState getLiftState() { return liftState; } public void setLiftState(LiftState liftState) { this.liftState = liftState; //通知各个实现类中 this.liftState.setLiftContext(this); } /** * 环境类定义状态转化方法 * @param state */ public void changeState(String state) { switch (state) { case Constant.OPEN: this.setLiftState(new LiftOpen()); break; case Constant.CLOSE: this.setLiftState(new LiftClose()); break; case Constant.RUNNING: this.setLiftState(new LiftRunning()); break; case Constant.STOP: this.setLiftState(new LiftStop()); break; default: break; } } public void open() { this.liftState.openState(); } public void close() { this.liftState.closeState(); } public void running() { this.liftState.runningState(); } public void stop() { this.liftState.stopState(); } }
客户端
public class LiftClient { public static void main(String[] args) { LiftContext liftContext = new LiftContext(); liftContext.changeState(Constant.OPEN); liftContext.open(); liftContext.close(); liftContext.running(); liftContext.stop(); } }
总结
状态模式:主要理解状态和行为。状态是如何产生的,以及这个状态怎么过渡到其他状态(执行动作)。
或者点击下方超链接:
史上最全Java面试题,41个方向!一网打尽!
参考资料:
1.状态模式笔记
2.《Java 设计模式》
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算