状态模式
状态模式(State):当一个对象的内在状态变化时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
当然了,如果这个状态判断很简单,那么就没必要使用状态模式了。
状态模式(State)结构图
-
State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
public abstract class State {
abstract void handle(Context context);
}
-
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
// 具体状态A类
public class ConcreteStateA extends State {
@Override
void handle(Context context) {
// 设置下一个状态是B类对象
context.setState(new ConcreteStateB());
}
}
// 具体状态B类
public class ConcreteStateB extends State {
@Override
void handle(Context context) {
// 设置下一个状态是A类对象
context.setState(new ConcreteStateA());
}
}
-
Context,维护一个State对象,这个实例对象定义当前的状态
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
System.out.println("当前状态:" + this.state.getClass().getName());
}
public void request() {
this.state.handle(this);
}
}
-
客户端,多次调用切换状态
Context context = new Context(new ConcreteStateA());
context.request();
context.request();
context.request();
context.request();
实例
例:将工作时的工作状态使用编程方式实现一下:
臃肿实现方式:
static int hour = 0;
static boolean workFinished = false;
static void writeProgram() {
if (hour < 12) {
System.out.println("当前时间:" + hour + "点 上午工作 精神百倍!");
} else if (hour < 13) {
System.out.println("当前时间:" + hour + "点 饿了,去干饭,犯困,午休");
} else if (hour < 17) {
System.out.println("当前时间:" + hour + "点 下午状态还行,继续努力");
} else {
if (workFinished) {
System.out.println("当前时间:" + hour + "点 下班走人");
} else {
if (hour < 21) {
System.out.println("当前时间:" + hour + "点 加班哦,很疲惫");
} else {
System.out.println("当前时间:" + hour + "点 嘎嘎累 要睡着了");
}
}
}
}
-
客户端
hour = 9;
writeProgram();
hour = 11;
writeProgram();
hour = 12;
writeProgram();
hour = 13;
writeProgram();
workFinished = false;
hour = 19;
writeProgram();
那么可以看到,很多状态的切换都是这样子面向过程的方式实现。如何进行封装呢,就使用到了状态模式。
给个结构图
将所有时间段的工作状态都分别封装到一个类中。请看具体实现。
-
抽象状态类
public abstract class State {
abstract void writeProgram(Work w);
}
-
工作状态类
// 上午工作状态
public class ForenoonState extends State {
@Override
void writeProgram(Work w) {
if (w.getHour() < 12) {
System.out.println("当前时间:" + w.getHour() + "点 上午工作 精神百倍!");
} else {
w.setCurrent(new NoonState());
w.writeProgram();
}
}
}
// 中午工作状态
public class NoonState extends State {
@Override
void writeProgram(Work w) {
if (w.getHour() < 13) {
System.out.println("当前时间:" + w.getHour() + "点 饿了,去干饭,犯困,午休");
} else {
w.setCurrent(new AfternoonState());
w.writeProgram();
}
}
}
// 下午工作状态
public class AfternoonState extends State {
@Override
void writeProgram(Work w) {
if (w.getHour() < 17) {
System.out.println("当前时间:" + w.getHour() + "点 下午状态还行,继续努力");
} else {
w.setCurrent(new EveningState());
w.writeProgram();
}
}
}
// 晚间工作状态
public class EveningState extends State {
@Override
void writeProgram(Work w) {
if (w.isWorkFinished()) {
w.setCurrent(new RestState()); //完成任务下班
w.writeProgram();
} else {
if (w.getHour() < 21) {
System.out.println("当前时间:" + w.getHour() + "点 加班哦,很疲惫");
} else {
w.setCurrent(new SleepingState()); // 转入睡眠工作状态
w.writeProgram();
}
}
}
}
// 睡眠工作状态
public class SleepingState extends State {
@Override
void writeProgram(Work w) {
System.out.println("当前时间:" + w.getHour() + "点 嘎嘎累 要睡着了");
}
}
// 下班
public class RestState extends State {
@Override
void writeProgram(Work w) {
System.out.println("当前时间:" + w.getHour() + "点 下班走人");
}
}
-
客户端调用
Work w = new Work();
w.setHour(10);
w.writeProgram();
w.setHour(12);
w.writeProgram();
w.setHour(15);
w.writeProgram();
w.setHour(17);
w.writeProgram();
w.setWorkFinished(false);
w.setHour(19);
w.writeProgram();
w.setHour(22);
w.writeProgram();
好处和用处
好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开。
将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存放在于某个ConcreteState类中,所以通过定义新的子类可以很容易增加新的状态和转换。
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就需要考虑使用状态模式了了。
原文始发于微信公众号(小路同学ovo):设计模式–状态模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/267625.html