状态模式
本文主要参考自《大话设计模式》——第16章
1.定义
- 状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
- 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的简单逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
1.1 状态模式的简单实现:
- 以一个新闻稿件为例,有三个状态:草稿态、审批中态、已发布态,对应的状态流转示意图如下所示:
- 对应的状态模式代码如下:
/**
* @author ssk
* @date 2021/1/21 17:08
* @desc 状态机底层接口
*/
public interface State<EntityType> {
class StateName {
/**
* 草稿
*/
public static final String DRAFT = "draft";
/**
* 审批中
*/
public static final String ACTIVATING = "activating";
/**
* 激活
*/
public static final String ACTIVE = "active";
}
String stateName();
void edit(EntityType entity);
void active(EntityType entity);
void approve(EntityType entity);
void reject(EntityType entity);
}
/**
* @author ssk
* @date 2021/1/21 17:09
* @desc 状态机抽象类
*/
public abstract class AbstractState<EntityType> implements State<EntityType>{
@Override
public void edit(EntityType entity) {
this.unsupportedOperation();
}
@Override
public void active(EntityType entity) {
this.unsupportedOperation();
}
@Override
public void approve(EntityType entity) {
this.unsupportedOperation();
}
@Override
public void reject(EntityType entity) {
this.unsupportedOperation();
}
protected void unsupportedOperation(){
throw new RuntimeException("不支持的操作");
}
}
/**
* 新闻实体状态机
**/
public abstract class DocumentState extends AbstractState<DocumentPO> {
public static HashMap<String, DocumentState> stateHashMap = new HashMap<>();
static {
stateHashMap.put(StateName.DRAFT, new ContentInstanceDraftState());
stateHashMap.put(StateName.ACTIVATING, new ContentInstanceActiveState());
stateHashMap.put(StateName.ACTIVE, new ContentInstanceDeprecatedState());
}
public static DocumentState getInstanceByName(String stateName) {
DocumentState documentState = stateHashMap.get(stateName);
if(document==null){
throw new RuntimeException("对应状态不存在");
}
return documentState;
}
}
package state;
/**
* @author ssk
* @date 2021/1/21 17:16
* @desc 状态机-草稿态
*/
public class DocumentDraftState extends DocumentState{
@Override
public String stateName() {
return StateName.DRAFT;
}
@Override
public void edit(Document entity) {
// 编辑
}
@Override
public void active(Document entity) {
// 激活
}
}
package state;
/**
* @author ssk
* @date 2021/1/21 17:16
* @desc 状态机-激活中态
*/
public class DocumentActivatingState extends DocumentState {
@Override
public String stateName() {
return StateName.ACTIVATING;
}
@Override
public void approve(Document entity) {
// 审批通过
}
@Override
public void reject(Document entity) {
// 审批拒绝
}
}
package state;
/**
* @author ssk
* @date 2021/1/21 17:16
* @desc 状态机-激活态
*/
public class DocumentActivateState extends DocumentState{
@Override
public String stateName() {
return StateName.ACTIVE;
}
}
- 核心要点就是通过集成关系将状态流转机制定义好,如果是子状态机中没有复写的方法那么直接就会走到基类中不支持的操作。
2.为什么使用状态模式
- 状态模式的好处就是 将特定状态相关的行为局部化,并且将不同状态的行为分割开。这样做的目的就是为了消除庞大的条件分支语句,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。