1、概述
状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。
2、使用场景
1)如果对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式。
2)如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式。
3)当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式。
3、实例
有如下场景:
策划一场活动,活动有以下状态:
编辑,保存,提交,审核通过、审核拒绝、关闭、开启
其状态变化如下图所示:
状态.png创建状态的顶层抽象:
/**
* 抽象状态类
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
abstract class State {
public Activity activity;
public State(Activity activity) {
this.activity = activity;
}
/**
* 编辑
*/
public abstract State edit();
/**
* 保存
*/
public abstract State save();
/**
* 提交
*/
public abstract State submit();
/**
* 审核通过
*/
public abstract State pass();
/**
* 审核拒绝
*/
public abstract State reject();
/**
* 开启
*/
public abstract State start();
/**
* 关闭
*/
public abstract State close();
}
创建活动:
/**
* 活动
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class Activity {
/**
* 活动id
*/
private String id;
/**
* 活动名称
*/
private String name;
/**
* 更新状态
*/
public State changeState(State state){
return state;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Activity(String id, String name) {
this.id = id;
this.name = name;
}
}
创建几种状态的具体类:
package com.cloud.bssp.designpatterns.state;
/**
* 编辑状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class EditState extends State {
public EditState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("活动正在编辑");
return this;
}
@Override
public State save() {
System.out.println("活动已保存");
return activity.changeState(new SaveState(activity));
}
@Override
public State submit() {
System.out.println("活动已提交");
return activity.changeState(new SubmitState(activity));
}
@Override
public State pass() {
System.out.println("编辑中无法审核");
return this;
}
@Override
public State reject() {
System.out.println("编辑中无法审核");
return this;
}
@Override
public State start() {
System.out.println("编辑中无法开启");
return this;
}
@Override
public State close() {
System.out.println("编辑中无法关闭");
return this;
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 保存状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class SaveState extends State{
public SaveState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("活动正在编辑中");
return activity.changeState(new EditState(activity));
}
@Override
public State save() {
System.out.println("活动已保存");
return this;
}
@Override
public State submit() {
System.out.println("活动已提交");
return activity.changeState(new SubmitState(activity));
}
@Override
public State pass() {
System.out.println("保存状态无法审核");
return this;
}
@Override
public State reject() {
System.out.println("保存状态无法审核");
return this;
}
@Override
public State start() {
System.out.println("保存状态无法开启");
return this;
}
@Override
public State close() {
System.out.println("保存状态无法关闭");
return this;
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 提交状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class SubmitState extends State{
public SubmitState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("活动已提交,无法编辑");
return this;
}
@Override
public State save() {
System.out.println("活动已提交,无法保存");
return this;
}
@Override
public State submit() {
System.out.println("活动已提交,无法再次提交");
return this;
}
@Override
public State pass() {
System.out.println("活动已经审核通过");
return activity.changeState(new PassState(activity));
}
@Override
public State reject() {
System.out.println("活动已经审核拒绝");
return activity.changeState(new RejectState(activity));
}
@Override
public State start() {
System.out.println("未审核无法开启");
return this;
}
@Override
public State close() {
System.out.println("未审核无法关闭");
return this;
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 通过状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class PassState extends State{
public PassState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("审核通过无法编辑");
return this;
}
@Override
public State save() {
System.out.println("审核通过无法保存");
return this;
}
@Override
public State submit() {
System.out.println("审核通过无法提交");
return this;
}
@Override
public State pass() {
System.out.println("审核通过无法再次审核");
return this;
}
@Override
public State reject() {
System.out.println("审核通过无法再次审核");
return this;
}
@Override
public State start() {
System.out.println("活动已经开启");
return activity.changeState(new StartState(activity));
}
@Override
public State close() {
System.out.println("审核通过无法关闭");
return this;
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 拒绝状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class RejectState extends State{
public RejectState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("审核拒绝无法编辑");
return this;
}
@Override
public State save() {
System.out.println("审核拒绝无法保存");
return this;
}
@Override
public State submit() {
System.out.println("审核拒绝无法提交");
return this;
}
@Override
public State pass() {
System.out.println("审核拒绝无法再次审核");
return this;
}
@Override
public State reject() {
System.out.println("审核拒绝无法再次审核");
return this;
}
@Override
public State start() {
System.out.println("审核拒绝无法开启");
return this;
}
@Override
public State close() {
System.out.println("活动已经关闭");
return activity.changeState(new StartState(activity));
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 开启状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class StartState extends State{
public StartState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("已开启无法编辑");
return this;
}
@Override
public State save() {
System.out.println("已开启无法保存");
return this;
}
@Override
public State submit() {
System.out.println("已开启无法提交");
return this;
}
@Override
public State pass() {
System.out.println("已开启无法审核");
return this;
}
@Override
public State reject() {
System.out.println("已开启无法审核");
return this;
}
@Override
public State start() {
System.out.println("已开启无法再次开启");
return this;
}
@Override
public State close() {
System.out.println("活动已经关闭");
return activity.changeState(new CloseState(activity));
}
}
package com.cloud.bssp.designpatterns.state;
/**
* 关闭状态
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class CloseState extends State{
public CloseState(Activity activity) {
super(activity);
}
@Override
public State edit() {
System.out.println("活动正在编辑中");
return activity.changeState(new EditState(activity));
}
@Override
public State save() {
System.out.println("关闭状态无法保存");
return this;
}
@Override
public State submit() {
System.out.println("关闭状态无法提交");
return this;
}
@Override
public State pass() {
System.out.println("关闭状态无法再次审核");
return this;
}
@Override
public State reject() {
System.out.println("关闭状态无法再次审核");
return this;
}
@Override
public State start() {
System.out.println("关闭状态无法开启");
return this;
}
@Override
public State close() {
System.out.println("关闭状态无法再次关闭");
return this;
}
}
测试类:
package com.cloud.bssp.designpatterns.state;
/**
* 测试
* @date: 2021/1/25
* @author weirx
* @version 3.0
*/
public class TestDemo {
public static void main(String[] args) {
//初始化活动
Activity activity = new Activity("1", "活动1");
//初始化编辑状态
State state = new EditState(activity);
//保存
state = state.save();
//提交
state = state.submit();
//审核通过
state = state.pass();
//开启
state = state.start();
//开启状态下编辑
state.edit();
//开启状态下提交
state.submit();
}
}
结果:
活动已保存
活动已提交
活动已经审核通过
活动已经开启
已开启无法编辑
已开启无法提交
4、分析
State.png如上图所示,看到各个关系之间错综复杂,在每种状态里面不同的操作,会返回不同的状态结果,且对于其他状态没有影响。在Activity这个类里面,提供了一个公共的状态改变方法,只需声明局部变量State。
以上方式利于扩展,每个状态各司其职,充分解耦。
缩减上面的状态,以编辑状态为例,总结状态模式的几个主要组成如下图:
State.pngTestDemo:客户端。
State:顶层抽象。
Activity:状态上下文。
EditState:具体当前状态。
5、总结
优点:
1)单一职责原则。 将与特定状态相关的代码放在单独的类中。
2)开闭原则。 无需修改已有状态类和上下文就能引入新状态。
3)通过消除臃肿的状态机条件语句简化上下文代码。
缺点:
如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
网友评论