设计模式之状态模式

news/2024/11/8 18:43:21/

状态模式的定义是:当一个对象内在状态改变时允许其改变行为,这个对象看起来像是改变了自身所属的类。

该模式适合于对象具有有限的状态,并且在状态之间相互切换。

例如使用如下的条件分支语句也是属于状态的切换:

switch (action){  case "play":  state="playing";  break;    case "stop":  state="stopping";  break;
}

当后期状态增多和状态转换复杂之后,使用这种方式会对后续的维护增加困难。使用状态模式能有效解决这种维护的困难,通过将与状态相关的行为抽取到独立的状态类中, 让原对象将工作委派给这些类的实例, 而不是自行进行处理,将复杂度隔离在状态类中。

该模式中存在 3 类对象:

  1. Context 上下文:保持有状态类的引用
  2. State 抽象状态:定义状态的方法
  3. ConcreteState 具体状态
Context
- state
-changeState()
«interface»
State
+action()
ConcreteState
+action()

代码实现:

//抽象状态
public abstract class State {  protected Player player;  public State(Player player) {  this.player = player;  }  // 停止  public abstract void onStop();  // 播放  public abstract void onPlay();  
}
//具体状态:停止状态
public class StoppingState extends State{  public StoppingState(Player player) {  super(player);  }  @Override  public void onStop() {  System.out.println("已经停止");  }  @Override  public void onPlay() {  player.setState(new PlayingState(player));  player.setPlaying(true);  }  
}// 具体状态:播放状态
public class PlayingState extends State {  public PlayingState(Player player) {  super(player);  }  @Override  public void onStop() {  player.setState(new StoppingState(player));  player.setPlaying(false);  }  @Override  public void onPlay() {  System.out.println("已经在播放");  }  
}
//上下文对象
@Data  
public class Player {  private State state;  private boolean playing;  
}
Player player=new Player();  
//设置初始状态  
player.setState(new StoppingState(player));  
//播放  
player.getState().onPlay();  
System.out.println(player.getState());  
//停止  
player.getState().onStop();  
System.out.println(player.getState());

状态模式的优点是:

  1. 消除了复杂的条件分支语句
  2. 将状态相关的行为封装在状态类中

缺点是如果状态太少,使用状态模式会显得过于复杂。


http://www.ppmy.cn/news/97804.html

相关文章

C/C++开发,libiec61850库学习及运用

目录 一、libiec61850库下载编译 1.1 下载 1.2 linux编译: 1.3 win编译 二、案例编译测试 2.1 CMakeLists.txt调整(server_example_goose) 2.2 模型static_model.h/static_model.cpp生成 2.3 案例编译(server_goose) 2.4 客户端编译 2.5 运行测试 一、libiec61850…

logstash 采集应用日志切割问题

1.logstash [oswatch@rce1 conf]$ cat test.conf input { file { path=>["/tmp/test/test.log*"] } } output { stdout { codec=>rubydebug{} } } 2.python脚本: [oswatch@rce1 conf]$ cat t1.py #!/usr/bin/python # -*- coding: UTF-…

算法|9.从暴力递归到动态规划2

9.算法|从暴力递归到动态规划2 1.数字字符串转英文字符串 题意:规定1和A对应、2和B对应、3和C对应…26和Z对应,那么一个数字字符串比如"111”就可以转化为:“AAA”、“KA"和"AK” 给定一个只有数字字符组成的字符串str,返回…

采购申请审批测试

采购申请审批的配置并不难,但是总会有原因导致业务无审批策略,而且这个配置也比较脆弱,有时同步也会出现问题,小编利用这篇操作记录下测试结果。 1、项目类别的审批策略分类 下图是审批策略分类-项目类别不给值,测试…

使用sklearn进行机器学习案例(1)

文章目录 案例一. 加州房价预测案例二. MNIST手写数字识别案例三. 波士顿房价预测 案例一. 加州房价预测 线性回归通过对训练集进行训练,拟合出一个线性方程,使得预测值与实际值之间的平均误差最小化。这个过程可以使用梯度下降法等优化算法来实现。即通…

【MCS-51】中断系统原理及应用

中断是单片机中一个十分重要的功能,它的出现能够让我们的单片机在顺序执行命令时,具备应对特殊情况的能力。 目录 🌙通信方式 🍃无条件传送 🍃有条件传送 🍃DMA通信 🍃中断传送 &#x1…

CGAL4.4+VC2008编译

CGAL4.4VC2008编译 CGAL 一: CGAL是欧盟资助的基础几何库,很底层, 纯算法, 对于你的项目和科研都是不可多得的好东西, 废话一句, 国内做这样的东西, 估计会活不下去交不了差的. 不多介绍.送上 英文原址, 从软件角度, CGAL架构与STL模板库, 需要你有较好的C功底. 英文功底就不…

c primer plus学习笔记

1.int的大小恒定就是32位么? 不是的,int大小是跟着系统走的,不是在各个系统里固定不变的。 32位系统int就是32位。64位系统,int就是64位。short 和long的长度则跟着long走,一般来说int是32位,short就是16…