[设计模式]之十二:状态模式

定义

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

场景

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。

简单来说,就是不同状态对应不同的程序行为。我们可以用大量if/else或者switch代码去处理不同状态的逻辑。但这是面向过程的代码,我们可以用面向对象的方式,使用状态模式,轻松地切换不同的状态。

UML

示例代码

//声明一个状态接口,统一通过HandleState处理状态
interface IState {
	public void HandleState(StateManager manager);
}
//具体状态类 这里不同状态类可以做一些与这些状态相关的简单处理逻辑
public class ConcreteStateA implements IState {

	@Override
	public void HandleState(StateManager manager) {
		if (someState) {
			...
		} else {
			...
		}
      // 当前stateA 改变为 stateB
		manager.setState(new ConcreteStateB());
	}

}

public class ConcreteStateB implements IState {

	@Override
	public void HandleState(StateManager manager) {
      // 当前stateB 改变为 stateA
		manager.setState(new ConcreteStateA());
	}
	
}
//状态管理类 私有一个 state对象,通过开放外部接口updateState对状态更新
public class StateManager {
	private IState state;
	
	public IState getState() {
		return state;
	}

	public void setState(IState state) {
		System.out.println("Set new state " + state.getClass().getName());
		this.state = state;
	}

	public StateManager(IState state) {
		System.out.println("Current state is " + state.getClass().getName());
		this.state = state;
	}
	
	public void updateState() {
		state.HandleState(this);
	}
	
}
//客户代码
public static void main(String[] args) {

  //初始化一个状态管理对象,给他一个初始状态,随后的状态切换由各自具体state类处理,上层只需要在某些条件下进行触发更新状态操作即可
	StateManager manager = new StateManager(new ConcreteStateA());
	
	manager.updateState();
	manager.updateState();
	manager.updateState();
	
}
//输出
Current state is ConcreteStateA
Set new state ConcreteStateB
Set new state ConcreteStateA
Set new state ConcreteStateB

评价

  • 状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。
  • 状态模式的关键是引入了一个抽象类来专门表示对象的状态,这个类我们叫做抽象状态类,而对象的每一种具体状态类都继承了该类,并在不同具体状态类中实现了不同状态的行为,包括各种状态之间的转换。

优点

  • 封装了转换规则。
  • 枚举可能的状态,在枚举状态之前需要确定状态种类。
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微信公众号:Java团长

Java虚拟机:Java内存区域及对象

为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念。

13020
来自专栏数据小魔方

左手用R右手Python系列——循环中的错误异常规避

上一讲讲了R语言与Pyhton中的异常捕获与错误处理基本知识,今天以一个小案例来进行实战演练,让你的程序遇水搭桥,畅通无阻。 本案例目标网址,今日头条的头条指数...

35860
来自专栏微信公众号:Java团长

面试的角度诠释Java工程师(一)

我相信每一个程序员都是为了生活而努力着的。很多人因为兴趣,从此踏上了这条‘烧脑大行动’的金桥;也有很多人因为梦想和执着,奋不顾身融入这个职业;还有很多人因为被现...

9110
来自专栏企鹅号快讯

Java后台编程初学者,这些常识你都知道吗?

Java编程中的一些常识,希望有心学习的可以多看一眼,如果你是高手欢迎指点文中小编的不足,感谢支持。以下这些编程常识均由小编结合个人水平以及搜寻相关资料整理编辑...

209100
来自专栏用户2442861的专栏

python操作redis简单例子

#2、配置  配置一下吧,默认配置文件在: “/etc/redis/redis.conf”  绑定ip:  “bind 127.0.0.1″ -> “b...

28720
来自专栏高爽的专栏

Java线程(四):线程中断、线程让步、线程睡眠、线程合并

最近在Review线程专栏,修改了诸多之前描述不够严谨的地方,凡是带有Review标记的文章都是修改过了。本篇文章是插进来的,因为原来没有写,现在...

27900
来自专栏沈唁志

PHP的一句话木马代码和函数eval的简介

其实这段代码属于基础类的一句话,功能仅限于验证漏洞了,实际中太容易被查出来了,也就是早上雨落直接带图说检测到木马文件

47060
来自专栏coder修行路

《深入理解计算机系统》阅读笔记--程序的机器级表示(上)

编译器基于编程语言的规则,目标机器的指令集和操作系统遵循的惯例,经过一系列的阶段生成机器代码。GCC c语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的...

12900
来自专栏用户2442861的专栏

网易面试杂谈

http://blog.csdn.net/silangquan/article/details/18013967

8820
来自专栏九彩拼盘的叨叨叨

EditorConfig 介绍

当多人共同开发一个项目的时候,往往会出现大家用不同编辑器的情况。就前端开发者来说,有人喜欢 Sublime,有人喜欢 Webstorm , 也有人喜欢 Atom...

9710

扫码关注云+社区

领取腾讯云代金券