STATE(状态)模式
引子
场景
在我们软件开发的过程中,有许多对象是有状态的。而对象的行为会随着状态的改变而发生改变。例如开发一个电梯类,电梯有开门、关门、停止、运行等行为,同时电梯也会有开门状态、关门状态、停止状态、运行状态等不同的状态。电梯处于不同的状态时,对不同的行为会做出不同的动作。如当电梯处于开门状态时,电梯可以做关门动作;开门状态时,电梯一定是停止的,所以此时停止动作不会发生任何行为;开门状态时,电梯不能运行,所以运行动作也不会发生任何行为。如果我们使用条件判断语句实现上述逻辑,会出现大量的if else判断,或者switch case 语句。而且当需要增加一个状态时,这些条件判断语句都需要修改。例如增加一个维修状态,不仅会修改原有的if else,还有引入维修状态的判断和执行逻辑。
模式引出
为了解决上面说的不同状态不同行为的问题,引出了状态模式。一个对象在某一时刻只有一种状态,根据对象的状态决定对象的某一个行为的具体动作。
意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性
- 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
结构
组成
- 环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
- 抽象状态类(State): 定义一个接口以封装与Context的一个特定状态相关的行为。
- 具体状态类(ConcreteState):
每一子类实现一个与Context的一个状态相关的行为。
例子
电梯类:
/**
* 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
*/
public class Lift {
// 定义出所有的电梯状态
public static final LiftState OPENNINGSTATE = new OpeningState();
public static final LiftState CLOSEINGSTATE = new ClosingState();
public static final LiftState RUNNINGSTATE = new RunningState();
public static final LiftState STOPPINGSTATE = new StoppingState();
// 定义一个当前电梯状态
private LiftState liftState;
public boolean open() {
return liftState.open(this);
}
public boolean close() {
return liftState.close(this);
}
public boolean run() {
return liftState.run(this);
}
public boolean stop() {
return liftState.stop(this);
}
public LiftState getLiftState() {
return liftState;
}
public void setLiftState(LiftState liftState) {
this.liftState = liftState;
}
}
状态接口:
/**
*
* 定义一个电梯的状态接口
*/
public abstract class LiftState {
// 首先电梯门开启动作
abstract boolean open(Lift lift);
// 电梯门有开启,那当然也就有关闭了
abstract boolean close(Lift lift);
// 电梯要能上能下,跑起来
abstract boolean run(Lift lift);
// 电梯还要能停下来,停不下来那就扯淡了
abstract boolean stop(Lift lift);
abstract LiftState getState();
}
具体状态类:
open状态类:
/**
* 在电梯门开启的状态下能做什么事情
*/
public class OpeningState extends LiftState {
@Override
boolean open(Lift lift) {
System.out.println("The lift is opening now, no need to reopen.");
return false;
}
/**
* 开启当然可以关闭了,我就想测试一下电梯门开关功能
*/
@Override
boolean close(Lift lift) {
System.out.println("OpeningState to close the lift door. The lift is closed now.");
//状态修改
lift.setLiftState(Lift.CLOSEINGSTATE);
return true;
}
@Override
boolean run(Lift lift) {
System.out.println("The lift is opening, can not run!!");
return false;
}
@Override
boolean stop(Lift lift) {
System.out.println("The lift is opening, of course it is stopped.");
return false;
}
@Override
LiftState getState() {
return Lift.OPENNINGSTATE;
}
}
close状态类:
public class ClosingState extends LiftState {
@Override
boolean open(Lift lift) {
System.out.println("ClosingState to open the lift door. The lift is open now.");
//状态修改
lift.setLiftState(Lift.OPENNINGSTATE);
return true;
}
@Override
boolean close(Lift lift) {
System.out.println("The lift is closed now, have no need to reclose!!");
return false;
}
@Override
boolean run(Lift lift) {
System.out.println("ClosingState to run the lift. The lift is running now.");
lift.setLiftState(Lift.RUNNINGSTATE);
return true;
}
@Override
boolean stop(Lift lift) {
System.out.println("ClosingState to stop the lift. The lift is stopped now.");
lift.setLiftState(Lift.STOPPINGSTATE);
return true;
}
@Override
LiftState getState() {
return Lift.CLOSEINGSTATE;
}
}
stop状态类:
public class StoppingState extends LiftState {
@Override
boolean open(Lift lift) {
System.out.println("StoppingState to open the lift door. the lift is open now.");
lift.setLiftState(Lift.OPENNINGSTATE);
return true;
}
@Override
boolean close(Lift lift) {
//停止状态关门?电梯门本来就是关着的!
System.out.println(" the lift is closed, have no need to reclose!");
return false;
}
@Override
boolean run(Lift lift) {
System.out.println("StoppingState to run the lift. the lift is running now.");
lift.setLiftState(Lift.RUNNINGSTATE);
return true;
}
@Override
boolean stop(Lift lift) {
System.out.println("the lift is stop now, have no need to restop!");
return false;
}
@Override
LiftState getState() {
// TODO Auto-generated method stub
return Lift.STOPPINGSTATE;
}
}
run状态类:
public class RunningState extends LiftState {
@Override
boolean open(Lift lift) {
System.out.println("The lift is running, can not be opened!!");
return false;
}
@Override
boolean close(Lift lift) {
System.out.println("The lift is running, the lift door is closed. have no need to reclose.");
return false;
}
@Override
boolean run(Lift lift) {
System.out.println("The lift is running. have no need to rerun.");
return false;
}
@Override
boolean stop(Lift lift) {
System.out.println("RunningState to stop the lift. The lift is stopped now.");
lift.setLiftState(Lift.STOPPINGSTATE);
return true;
}
@Override
LiftState getState() {
return Lift.RUNNINGSTATE;
}
}
测试类:
public class Client {
public static void main(String[] args) {
Lift context = new Lift();
context.setLiftState(Lift.CLOSEINGSTATE);
context.open();
context.close();
context.run();
context.stop();
context.run();
context.open();
context.open();
context.stop();
context.open();
}
}
优点
- 封装了转换规则
- 枚举可能的状态,在枚举状态之前需要确定状态种类。
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点
- 状态模式的使用必然会增加系统类和对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
- 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
参考:
《设计模式可复用面向对象软件的基础》
http://blog.csdn.net/hguisu/article/details/7557252#comments
http://blog.csdn.net/chenssy/article/details/11096391
http://men4661273.iteye.com/blog/1633973
STATE(状态)模式的更多相关文章
- C++设计模式-State状态模式
State状态模式作用:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. UML图如下: State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为. ...
- State状态模式
1.简介 在日常开发中,某些对象的状态如果发生改变,对应的行为也将发生改变,那么如何在运行时根据对象的状态动态的改变对象的行为,同时不产生紧耦合关系(即使用if else或者swith所带来的紧耦合关 ...
- 设计模式---状态变化模式之state状态模式(State)
前提:状态变化模式 在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案. 典型模式 状态模式:Stat ...
- 设计模式21:State 状态模式(行为型模式)
State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...
- 19、State 状态模式
“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换.就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流 ...
- 程序设计模式 —— State 状态模式
我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...
- JAVA设计模式--State(状态模式)
状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...
- 设计模式之 State 状态模式
状态模式的核心在于 1. 状态的转换导致行为(Handle)的差异,比如人的状态是饿的时候,吃(Handle)的行为是2个馒头,人状态是不太饿的时候,吃(Handle)的行为是半个馒头 2. Stat ...
- State 状态模式
简介 状态模式允许一个对象在其内部[状态]改变的时候改变其[行为].这个对象看上去就像是改变了它的类一样. 用一句话来表述,状态模式把所研究的对象的[行为]包装在不同的[状态对象]里,[每一个状态对象 ...
- 设计模式 ( 十八 ):State状态模式 -- 行为型
1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ellse语句来做状态判断来进行不同情况的处理.但是对 ...
随机推荐
- win10被微软流氓更新后编译基于visual Studio的web项目报[ArgumentOutOfRangeException: 指定的参数已超出有效值的范围
最近忙得算焦头烂额.就在这个时候.一个不留神.微软的自动更新打开了.这流氓就在我百忙之中强迫我休息了一个多小时. 焦急等待它更新完以后赶紧打开visual studio跑代码.运行好几次都报错.想想不 ...
- 【微信小程序】对微信http请求API的封装,方便对错误码进行处理
/** * App 微信配置文件app.js * author: nujey * versions: 1.0.0 */ App({ /** * @param {Object ...
- 关于myeclipse启动报错:An internal error has occurred. java.lang.NullPointerException解决办法
启动myeclipse报错,百度了一下网友处理方式,对比日志,发现现在已有的教程真的是巨人坑: 如果出现了上述的错误按照如下的3个步骤解决:1.首先关闭MyEclipse工作空间.2.然后删除工作空间 ...
- 探寻 webpack 插件机制
webpack 可谓是让人欣喜又让人忧,功能强大但需要一定的学习成本.在探寻 webpack 插件机制前,首先需要了解一件有意思的事情,webpack 插件机制是整个 webpack 工具的骨架,而 ...
- [LeetCode] Kth Smallest Number in Multiplication Table 乘法表中的第K小的数字
Nearly every one have used the Multiplication Table. But could you find out the k-th smallest number ...
- PHPCMS v9.6.0 wap模块 SQL注入
调试这个漏洞的时候踩了个坑,影响的版本是php5.4以后. 由于漏洞是由parse_str()函数引起的,但是这个函数在gpc开启的时候(也就是php5.4以下)会对单引号进行过滤\' . 看这里: ...
- php代码审计之变量覆盖
变量覆盖一般由这四个函数引起 <?php $b=3; $a = array('b' => '1' ); extract($a,EXTR_OVERWRITE); print_r($b); / ...
- bzoj 5212: [Zjoi2018]历史
Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有n个城市,这n个城市被恰好n?1条双向道路联通,即任意两个城 ...
- [洛谷]P3613 睡觉困难综合征
题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对 ...
- [bzoj4866] [Ynoi2017]由乃的商场之旅
来自FallDream的博客,未经允许,请勿转载,谢谢, 由乃有一天去参加一个商场举办的游戏.商场派了一些球王排成一行.每个人面前有几堆球.说来也巧,由乃和你一样,觉得这游戏很无聊,于是决定换一个商场 ...