状态模式(State):当一个对象的内在状态改变时允许改变其行为,这个对象看起来是改变其类。
UML图:
package com.thpin.repository.designpattern;
public class StateDemo {
public static void main(String[] args) {
String state = "stateA";
if ("stateA".equals(state)) {
System.out.println("状态A 工作");
} else if ("stateB".equals(state)) {
System.out.println("状态B 工作");
}
/*
* 根据需求变更,还会有更多的状态
* 就会出现更多的if else
* 违反了开闭原则,因为对修改开放了
*/
// 而状态模式对保证了客户端的扩展开放,修改关闭
Context context = new Context(new StateA());
context.request();
context.request();
context.request();
context.request();
}
}
/*
* 上下文
*/
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}
/*
* 状态抽象类
*/
abstract class State {
public abstract void handle(Context context);
}
/*
* 状态A
*/
class StateA extends State {
public void handle(Context context) {
System.out.println("状态A 工作");// 当前状态A的工作
context.setState(new StateB());
}
}
/*
* 状态B
*/
class StateB extends State {
public void handle(Context context) {
System.out.println("状态B 工作");// 当前状态B的工作
context.setState(new StateA());
}
}
//-----以下是个人思维拓展,采用枚举的方式实现的状态模式,好像效果更好-----------
package com.thpin.repository.designpattern;
/**
* Created by lidaming on 2021-5-28.
*/
public class StateDemo {
public static void main(String[] args) {
Context context = new Context();
context.request();
context.request();
context.request();
context.request();
context.request();
}
}
class Context {
private StateEnum state = StateEnum.STATE_OFF;
public Context() {
}
public Context(StateEnum state) {
this.state = state;
}
public void request() {
state.handle(this);
}
public StateEnum getState() {
return state;
}
public void setState(StateEnum state) {
this.state = state;
}
}
enum StateEnum {
STATE_OFF("关", 0, 1),
STATE_ON("开", 1, 0);
// 枚举也可以很轻松的实现放大镜功能
// STATE_1("原始大小", 1, 2),
// STATE_2("二倍大小", 2, 3),
// STATE_3("三倍大小", 3, 4),
// STATE_4("四倍大小", 4, 1);
private String name;
private int type;
private int next;
StateEnum(String name, int type, int next) {
this.name = name;
this.type = type;
this.next = next;
}
public void handle(Context context) {
//这里的处理代码也许涉及spring注入的service对象,枚举不一定支持,读者自己验证
//以下有两种解决方案:
//1、可以调整handle(Context context,XXXService sevice)用参数传过来
//2、这部分逻辑操作可以放在Context.request()里面去处理,然后调用handle()更改状态
System.out.println(context.getState().getName());
context.setState(getStateByNext(context.getState().getNext()));
}
public String getName() {
return name;
}
public int getType() {
return type;
}
public int getNext() {
return next;
}
public StateEnum getStateByNext(int next) {
for (StateEnum state : values()) {
if (state.getType() == next) {
return state;
}
}
return STATE_OFF;
}
}
运行结果:
关
开
关
开
关
结果:
状态A 工作
状态A 工作
状态B 工作
状态A 工作
状态B 工作
状态模式主要解决的是控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把简单的判断逻辑简化。