网站首页 > java教程 正文
“
状态模式是一种行为型设计模式,通过在不同状态下对象行为的改变,简化了复杂的条件判断逻辑。以咖啡机为例,其多种状态如关机、待机、加热等,在不同状态下有不同行为,状态模式将每种状态及对应行为封装在各自类中,咖啡机类只需引用当前状态,需要时切换并调用相应行为方法,这降低了代码复杂度,提高了可读性和可维护性。
”
定义
状态模式(State Pattern)是一种行为型设计模式,它让你能在一个对象的内部状态改变时改变其行为,使其看起来就像改变了自身的类,状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
用举一个生活中常见的例子来解释状态模式:考虑一个咖啡机的工作过程,咖啡机有多种状态,比如:关机状态、待机状态、加水状态、加热状态、冲煮状态和缺水状态等,在不同的状态下,咖啡机的行为是不一样的,比如在关机状态下,你不能开始冲煮咖啡;在待机状态下,你可以添加咖啡豆或者水;在加热状态下,你需要等待直到加热完成才能开始冲煮;在冲煮状态下,咖啡机会自动完成冲煮过程并倒出咖啡。
如果把这些状态和行为都放在一个大的条件判断语句或者状态机里面,代码会变得非常复杂且难以维护,但是如果我们使用状态模式,就可以为每种状态创建一个类,每个类里面封装了在这种状态下咖啡机应该有的行为,然后咖啡机类里面只需要持有一个当前状态的引用,当需要改变状态时,就切换到对应的状态对象,然后调用该状态对象的行为方法。状态和行为紧密地绑定在一起,并且把状态的转换逻辑分散到各个状态类中去,降低了代码的复杂度,提高了代码的可读性和可维护性。
代码案例
反例
这是一个未使用状态模式的反例代码,在反例中,将模拟一个简单的电灯开关系统,电灯有三种状态:关闭(OFF)、打开(ON)和故障(BROKEN),并会在一个电灯类中使用大量的条件语句来处理这些状态,如下代码:
public class Light {
// 定义电灯的状态
private String state;
public Light() {
this.state = "OFF"; // 初始化状态为关闭
}
// 打开电灯
public void turnOn() {
if (state.equals("OFF")) {
System.out.println("The light is now ON.");
state = "ON";
} else if (state.equals("BROKEN")) {
System.out.println("The light is broken and cannot be turned on.");
} else {
System.out.println("The light is already ON.");
}
}
// 关闭电灯
public void turnOff() {
if (state.equals("ON")) {
System.out.println("The light is now OFF.");
state = "OFF";
} else if (state.equals("BROKEN")) {
System.out.println("The light is broken and cannot be turned off.");
} else {
System.out.println("The light is already OFF.");
}
}
// 电灯出故障
public void breakLight() {
if (!state.equals("BROKEN")) {
System.out.println("The light is now BROKEN.");
state = "BROKEN";
} else {
System.out.println("The light is already BROKEN.");
}
}
// 客户端调用案例
public static void main(String[] args) {
Light light = new Light();
// 打开电灯
light.turnOn();
// 再次尝试打开电灯
light.turnOn();
// 关闭电灯
light.turnOff();
// 让电灯出故障
light.breakLight();
// 尝试打开出故障的电灯
light.turnOn();
}
}
输出结果:
The light is now ON.
The light is already ON.
The light is now OFF.
The light is now BROKEN.
The light is broken and cannot be turned on.
上面例子中,Light 类包含了所有可能的状态转换逻辑,这导致了类中的方法(turnOn、turnOff 和 breakLight)包含了复杂的条件分支,这样的代码难以阅读和维护,尤其是当状态和行为变得更加复杂时。
上面的代码案例暴露除了诸多问题:
- 状态转换逻辑分散在多个方法中,难以统一管理。
- 随着状态数量的增加,条件分支的复杂性也会增加,导致代码难以理解和扩展。
- 状态和行为没有很好地封装在一起,违反了单一职责原则。
解决方法,可以使用状态模式解决这些问题,通过将每种状态封装成一个单独的类,将状态转换逻辑局部化,并且更容易地添加新的状态和行为。
正例
下面是一个使用状态模式实现的正例代码,继续以电灯开关系统为例,这次使用状态模式来管理电灯的不同状态。
首先,定义一个State接口,它表示一个状态,并声明所有状态都应该有的行为,如下代码:
// 状态接口
public interface State {
void turnOn(Context context);
void turnOff(Context context);
void breakLight(Context context);
}
然后,为每种状态创建具体的实现类,如下代码:
// 关闭状态
public class OffState implements State {
@Override
public void turnOn(Context context) {
System.out.println("The light is now ON.");
context.setState(new OnState()); // 切换到打开状态
}
@Override
public void turnOff(Context context) {
System.out.println("The light is already OFF.");
}
@Override
public void breakLight(Context context) {
System.out.println("The light is broken.");
context.setState(new BrokenState()); // 切换到故障状态
}
}
// 打开状态
public class OnState implements State {
@Override
public void turnOn(Context context) {
System.out.println("The light is already ON.");
}
@Override
public void turnOff(Context context) {
System.out.println("The light is now OFF.");
context.setState(new OffState()); // 切换到关闭状态
}
@Override
public void breakLight(Context context) {
System.out.println("The light is broken.");
context.setState(new BrokenState()); // 切换到故障状态
}
}
// 故障状态
public class BrokenState implements State {
@Override
public void turnOn(Context context) {
System.out.println("The light is broken and cannot be turned on.");
}
@Override
public void turnOff(Context context) {
System.out.println("The light is broken and cannot be turned off.");
}
@Override
public void breakLight(Context context) {
System.out.println("The light is already BROKEN.");
}
}
接下来,创建一个Context类,它表示电灯,并持有当前状态的引用,如下代码:
// 电灯上下文,持有当前状态
public class Context {
private State state;
public Context() {
this.state = new OffState(); // 初始化状态为关闭
}
public void setState(State state) {
this.state = state;
}
public void turnOn() {
state.turnOn(this);
}
public void turnOff() {
state.turnOff(this);
}
public void breakLight() {
state.breakLight(this);
}
}
最后,在client代码中演示如何使用这个状态模式实现的电灯系统,如下代码:
public class Client {
public static void main(String[] args) {
Context light = new Context();
// 打开电灯
light.turnOn();
// 再次尝试打开电灯
light.turnOn();
// 关闭电灯
light.turnOff();
// 让电灯出故障
light.breakLight();
// 尝试打开出故障的电灯
light.turnOn();
// 尝试关闭出故障的电灯
light.turnOff();
}
}
1输出结果:
The light is now ON.
The light is already ON.
The light is now OFF.
The light is broken.
The light is broken and cannot be turned on.
The light is broken and cannot be turned off.
在正例中,每个状态(OffState、OnState和BrokenState)都封装了其在该状态下电灯应有的行为,并且Context类(电灯)通过setState方法来改变当前状态,这种方式使得状态转换逻辑更加清晰,并且容易扩展新的状态和行为。
核心总结
状态模式在开发过程中中极为实用,它的优点很明显:它使代码结构更清晰,易于维护,通过将行为与状态关联,状态模式让对象在其内部状态改变时自动改变行为,无需过多外部干预,可以方便地增加新的状态和行为,从而提高了系统的可扩展性。
使用状态模式核心的缺点是可能会引入较多的类,导致系统复杂度增加,同时,如果状态转换逻辑复杂,可能会使代码变得难以理解和管理。在使用时要明确状态转换的逻辑和行为,避免过度复杂的设计,要合理划分状态和行为,保持类的简洁和职责单一。
- 上一篇: 连微服务Nacos配置中心都不了解,那你可能注定就是个码农
- 下一篇: 设计模式:状态模式
猜你喜欢
- 2024-11-26 Java线程调度&状态
- 2024-11-26 JAVA线程状态及实现
- 2024-11-26 学Java很久了,但越学越“糊涂”,Java学到什么程度才叫精通呢?
- 2024-11-26 设计模式之状态模式
- 2024-11-26 java开发工具IntelliJ IDEA Git使用教程:检查项目状态
- 2024-11-26 java设计模式状态模式
- 2024-11-26 Java线程的6种状态及切换,透彻讲解
- 2024-11-26 计算机等级二考试辅导:Java IO机试题及解答(第2部分)
- 2024-11-26 清华教授,手把手带你深度解读Java枚举,理论与实战齐飞
- 2024-11-26 Java试题分享211111
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)