状态模式在 Java 中的应用
最编程
2024-04-16 17:48:40
...
这是我参与更文挑战的第7天,活动详情查看: 更文挑战
业务场景
学过设计模式的兄弟们一定经常在写代码的时候思索, 倒底何时才能使用我的洪荒之力呢?
笔者最近恰好就遇到了最合适不过的需求, 简单介绍下:
- 需要一直对设备进行监控
- 可以对设备发送向上移动/向下移动/停止移动指令
- 设备离线时, 需要重连并进行初始化
- 设备初始化过程中, 需要获取设备情况
- 设备正常运行时, 需要获取设备坐标
方案
按照上面的需求, 我们很容易写出如下结构的代码:
if (device.getStatus() == Device.Status.OFFLINE) {
// 业务代码
} else if (device.getStatus() == Device.Status.INIT) {
// 业务代码
}
...
乍一看逻辑非常严谨, 但实际情况是, 在向上移动的方法中, 会出现这一堆if, 同时它也会出现在向下移动的方法中, 停止移动的方法中
此时, 我们应该使用状态模式
当一堆相同情况的if语句出现在两个或多个不同的方法中时, 我们就该考虑用状态(State)去替换它
这里多说一句, 状态模式和策略模式的区别是, 状态模式下用户无法感知和参与对象的状态变化, 而策略模式是可以的
编写状态类
首先, 创建一个基础状态类, BaseState.java:
public abstract class BaseState {
Device device;
protected BaseState(Device device) {
this.device = device;
}
/**
* 心跳链接
*/
public abstract void heartBeat();
}
继续创建离线状态, 继承自基础状态, OffLineState.java:
public class OffLineState extends BaseState {
public OffLineState(Device device) {
super(device);
}
@Override
public void heartBeat() {
homing();
}
public void homing() {
try {
device.homing();
device.setState(new InitState(device));
} catch (IOException e) {
device.setState(new OffLineState(device));
}
}
}
可以看到, 状态的变化是在内部, 用户无法感知
接下来创建初始化类, InitState.java:
public class InitState extends BaseState {
public InitState(Device device) {
super(device);
}
@Override
public void heartBeat() {
try {
if (device.isMove()) {
return;
}
device.setZeroPosition(device.currentPosition());
device.setState(new OnLineState(device));
} catch (IOException e) {
device.setState(new OffLineState(device));
}
}
}
替换方法
接下来, 我们只需要在具体的业务逻辑中, 将代码device.heartBeat()
替换为device.getState().heartBeat()
这里不再赘述, 简单展示下笔者的业务相关代码:
public class Connector {
private static final int INTERVAL = 2000;
@Async
public void connect(Device device) {
try {
while(true) {
device.getState().heartBeat();
Thread.sleep(INTERVAL);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
总结
最后总结下状态模式的特点:
- 状态类拥有相同的public方法
- 状态类拥有一个属性指向使用此状态的实体类
- 状态类在内部自动切换状态, 用户无法感知
- 用于替换大块重复出现的if语句
推荐阅读
-
文明之旅(一):解开文明的密码--遥感技术在考古学中的应用与探索
-
Java 面试问题:解释 Java 中的并发工具类 ConcurrentHashMap 如何工作,并列举经典应用示例
-
贪婪算法在 Python、JavaScript、Java、C++ 和 C# 中的多种实现及其在硬币变化、分数骑士、活动选择和使用哈夫曼编码的最小生成树问题中的应用实例
-
连体网络孪生神经网络及其在医疗场景中的应用
-
使用 `react-google-login` 在 React 应用程序中添加 Google 登录的指南
-
如何在 Google Chrome 浏览器中启用暗黑模式?在 Google Chrome 浏览器中设置黑暗模式的步骤
-
python 数据分析在电力行业中的应用 python 电影数据分析报告
-
在 Java 中输入单个字符的 2 种方法:
-
在 Java 中获取键盘输入值的三种方法
-
智能电网技术在电力调度自动化中的应用