最近项目中有个项目是用到了状态得操作,比如从审核到审核通过再到审核查看审核中再到审核完成等一系列得状态。
看了一眼开发写的得代码,只能说有点想跑路得感觉,搂一眼这个代码。
一大串if和else得判断,类似于这种工作流为核心得项目就应该用到状态模式啊!这也可能是当时项目急,压根就没有做设计,这样后续维护得人可就要混不下去了,光是代码就不想看了。
废话不说了,根据这个项目想到了一个设计模式即状态模式,照着往上得一些资料写了一个demo。
看下流程:
设计UML :
包结构:
创建接口状态state:
代码语言:javascript复制public interface State {
/**
* 定价发布
*/
void makePriceEvent(Context context);
/**
* 接单
*/
void acceptOrderEvent(Context context);
/**
* 无人接单失效
*/
void notPeopleAcceptEvent(Context context);
/**
* 付款
*/
void payOrderEvent(Context context);
/**
* 接单有人支付失效
*/
void orderFailureEvent(Context context);
/**
* 反馈
*/
void feedBackEvent(Context context);
/**
* 得到状态
*
* @return
*/
String getCurrentState();
}
创建状态默认是默认实现:
代码语言:javascript复制public abstract class AbstractState implements State{
protected static final RuntimeException EXCEPTION = new RuntimeException("操作流程不允许");
@Override
public void makePriceEvent(Context context) {
throw EXCEPTION;
}
@Override
public void acceptOrderEvent(Context context) {
throw EXCEPTION;
}
@Override
public void notPeopleAcceptEvent(Context context) {
throw EXCEPTION;
}
@Override
public void payOrderEvent(Context context) {
throw EXCEPTION;
}
@Override
public void orderFailureEvent(Context context) {
throw EXCEPTION;
}
@Override
public void feedBackEvent(Context context) {
throw EXCEPTION;
}
}
创建上下文设置:
代码语言:javascript复制public class Context extends AbstractState{
private State state;
/**
* 定价发布
*/
@Override
public void makePriceEvent(Context context) {
state.makePriceEvent(this);
getCurrentState();
}
/**
* 接单
*/
@Override
public void acceptOrderEvent(Context context) {
state.acceptOrderEvent(this);
getCurrentState();
}
/**
* 无人接单失效
*/
@Override
public void notPeopleAcceptEvent(Context context) {
state.notPeopleAcceptEvent(this);
getCurrentState();
}
/**
* 付款
*/
@Override
public void payOrderEvent(Context context) {
state.payOrderEvent(this);
getCurrentState();
}
/**
* 接单有人支付失效
*/
@Override
public void orderFailureEvent(Context context) {
state.orderFailureEvent(this);
getCurrentState();
}
/**
* 反馈
*/
@Override
public void feedBackEvent(Context context) {
state.feedBackEvent(this);
getCurrentState();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
@Override
public String getCurrentState() {
System.out.println("当前状态 : " state.getCurrentState());
return state.getCurrentState();
}
}
创建状态枚举:
代码语言:javascript复制public enum StateEnum {
//待付款
NOT_PAY(1, "待付款"),
//已付款
PAID(2, "已付款"),
//已完结
FEED_BACKED(3, "已完结");
private int key;
private String value;
StateEnum(int key, String value) {
this.key = key;
this.value = value;
}
public String getValue() {
return value;
}
}
准备工作做好了,然后就可以编写自己每个业务得状态流程了。
发布业务状态:
代码语言:javascript复制public class PublishState extends AbstractState {
/**
* 接单
*/
@Override
public void acceptOrderEvent(Context context) {
// 把当前状态设置为 NotPayState 未付款状态
// 至于设置成什么状态,由自己得流程业务决定
context.setState(new NotPayState());
}
/**
* 无人接单失效
*/
@Override
public void notPeopleAcceptEvent(Context context) {
context.setState(new FeedBackState());
}
/**
* 继承没有实现得方法做相应得操作
*
* @return
*/
@Override
public String getCurrentState() {
return null;
}
}
未付款状态:
代码语言:javascript复制public class NotPayState extends AbstractState {
@Override
public void payOrderEvent(Context context) {
context.setState(new PaidState());
}
@Override
public void feedBackEvent(Context context) {
context.setState(new FeedBackState());
}
@Override
public String getCurrentState() {
return StateEnum.NOT_PAY.getValue();
}
}
付费状态:
代码语言:javascript复制public class PaidState extends AbstractState {
@Override
public void feedBackEvent(Context context) {
context.setState(new FeedBackState());
}
@Override
public String getCurrentState() {
return StateEnum.PAID.getValue();
}
}
反馈完结状态:
代码语言:javascript复制public class FeedBackState extends AbstractState {
@Override
public String getCurrentState() {
return StateEnum.FEED_BACKED.getValue();
}
}
业务demo也编写完成,接着编写一个测试类也就类似接口调用
代码语言:javascript复制package money;
import money.state.PublishState;
/**
* 测试
*
* @author :lyj
* @email: :liyj@nysoftland.com.cn
* @date :2020/10/22 16:47
*/
public class Test {
public static void main(String[] args) {
// 创建上下问对象
Context context = new Context();
// 设置当前状态(发布业务)
context.setState(new PublishState());
//然后可以根据操作变化状态.
//publish --> not pay
context.acceptOrderEvent(context);
//not pay --> paid
context.payOrderEvent(context);
// paid --> pay end
context.feedBackEvent(context);
// 如果调用业务中没有得状态将失败抛出异常
// context.makePriceEvent(context);
}
}
看下效果:
到此状态模式demo就初步完成了,虽然有点绕但是可读和可维护性还是非常好得。