在软件开发过程中,应用程序中的部分对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态。
当有状态的对象与外部事件产生互动时,其内部状态就会发生改变,从而使其行为也发生改变。
对这种有状态的对象编程,传统的解决方案是:将这些所有可能发生的情况全都考虑到,然后使用 if-else 或 switch-case 语句来做状态判断,再进行不同情况的处理。
但是显然这种做法对复杂的状态判断存在天然弊端,条件判断语句会过于臃肿,可读性差,且不具备扩展性,维护难度也大。且增加新的状态时要添加新的 if-else 语句,这违背了“开闭原则”,不利于程序的扩展。
以上问题如果采用“状态模式”就能很好地得到解决。状态模式的解决思想是:当控制一个对象状态转换的条件表达式过于复杂时,把相关“判断逻辑”提取出来,用各个不同的类进行表示,系统处于哪种情况,直接使用相应的状态类对象进行处理,这样能把原来复杂的逻辑判断简单化,消除了 if-else、switch-case 等冗余语句,代码更有层次性,并且具备良好的扩展力。
优点:
缺点:
一句话总结
把判断对象状态的复杂“判断逻辑”提取到子类中,允许子类在其内部状态发生改变时改变其行为。
订单的状态有很多种,有待支付、待发货等等,而且每种状态下的订单处理逻辑也比较多,在这个过程中如果使用硬编码,我们就需要一系列的 if-else 语句来检查订单的当前状态、可执行操作以及这两个组合得到的下一个应该被流转的状态值。如果订单的状态流转很复杂,代码逻辑就会很复杂,可拓展性弱,可读性低,后期维护困难。
对于这种情况,我们可以使用状态机模式来处理。
上面是状态的模式的雷图,主要包含三种角色:
OrderContext代码实现如下:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/8 4:10 下午
* @Version 1.0
*/
public class OrderContext {
State state = State.WAIT_PAY;
OrderState orderState = new WaitPay();
public void OrderContext(){
orderState = new WaitPay();
}
public void Handle(){
orderState.Handle(this);
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public OrderState getOrderState(){
return this.orderState;
}
public void setOrderState(OrderState orderState) {
this.orderState = orderState;
}
/**
* main函数
* @param args
*/
public static void main(String[] args) {
OrderContext orderContext = new OrderContext();
orderContext.Handle();
orderContext.Handle();
orderContext.Handle();
orderContext.Handle();
orderContext.Handle();
}
}
OrderState的代码实现如下:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/2 2:15 下午
* @Version 1.0
*/
public abstract class OrderState {
public abstract void Handle(OrderContext orderContext);
}
WaitPay、WaitRecv、WaitSend、WaitValuate、Finished 的代码实现如下:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/2 2:15 下午
* @Version 1.0
*/
class WaitPay extends OrderState {
@Override
public void Handle(OrderContext orderContext) {
if (orderContext.getState() == State.WAIT_PAY){
System.out.println("用户已付款,等待发货");
orderContext.setState(State.WAIT_SEND);
orderContext.setOrderState(new WaitSend());
} else {
System.out.println("等待用户支付,当前订单状态为:" + orderContext.getState().getName());
}
}
}
class WaitSend extends OrderState {
@Override
public void Handle(OrderContext orderContext){
if (orderContext.getState() == State.WAIT_SEND){
System.out.println("卖家已发货,等待订单签收");
orderContext.setState(State.WAIT_RECV);
orderContext.setOrderState(new WaitRecv());
} else {
System.out.println("等待卖家发货,当前订单状态为:" + orderContext.getState().getName());
}
}
}
class WaitRecv extends OrderState {
@Override
public void Handle(OrderContext orderContext){
if (orderContext.getState() == State.WAIT_RECV){
System.out.println("订单已签收,等待用户评价");
orderContext.setState(State.WAIT_VALUATE);
orderContext.setOrderState(new WaitValuate());
} else {
System.out.println("等待用户签收订单,当前订单状态为:" + orderContext.getState().getName());
}
}
}
class WaitValuate extends OrderState {
@Override
public void Handle(OrderContext orderContext){
if (orderContext.getState() == State.WAIT_VALUATE){
System.out.println("用户已评价,订单关闭");
orderContext.setState(State.FINISHED);
orderContext.setOrderState(new Finished());
} else {
System.out.println("等待卖家发货,当前订单状态为:" + orderContext.getState().getName());
}
}
}
class Finished extends OrderState{
@Override
public void Handle(OrderContext orderContext){
if (orderContext.getState() == State.FINISHED){
System.out.println("订单已完成");
} else {
System.out.println("等待订单完成,当前订单状态为:" + orderContext.getState().getName());
}
}
}
State枚举类的实现代码如下:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/2 2:07 下午
* @Version 1.0
*/
public enum State {
WAIT_PAY(1, "待付款"),
WAIT_SEND(2, "待发货"),
WAIT_RECV(3, "待签收"),
WAIT_VALUATE(4, "待评价"),
FINISHED(5, "订单已完成");
private final int id;
private final String name;
State(int id, String name){
this.id = id;
this.name = name;
}
State(State state){
this.id = state.id;
this.name = state.name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
运行结果如下:
以上就是状态机的详细讲解了,在运行后,我发现一个问题,各个具体状态之间(WaitPay、WaitRecv、WaitSend、WaitValuate、Finished),需要依赖自己要状态跳转的类,这样耦合度就增加了,有没有更好的办法呢?
于是,我在上面的版本上,又优化了一版。
相较于上个版本,此版本仅增加了一个Active枚举类,在各个状态类中,仅需要关注触发的条件和跳转到的恶状态即可,不需要知道别的具体处理类,更大限度的减少了耦合性。
Active状态实现:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/2 2:24 下午
* @Version 1.0
*/
public enum Active {
ACTIVE_PAY(1, "付款"),
ACTIVE_SEND(2, "发货"),
ACTIVE_RECV(3, "签收"),
ACTIVE_VALUATE(4, "评价"),
ACTIVE_CACLE(5, "取消");
private final int id;
private final String name;
Active(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
OrderContext实现
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/8 4:10 下午
* @Version 1.0
*/
public class OrderContext {
OrderState orderState;
public void OrderContext(){
orderState = new WaitPay();
}
public void Handle(Active active){
orderState.Handle(active);
}
public void setOrderState(OrderState orderState) {
this.orderState = orderState;
}
public static void main(String[] args) {
OrderContext orderContext = new OrderContext();
orderContext.setOrderState(new WaitPay());
orderContext.Handle(Active.ACTIVE_PAY);
System.out.println("-------");
orderContext.Handle(Active.ACTIVE_VALUATE);
System.out.println("-------");
orderContext.setOrderState(new WaitSend());
orderContext.Handle(Active.ACTIVE_SEND);
orderContext.setOrderState(new WaitRecv());
orderContext.Handle(Active.ACTIVE_RECV);
orderContext.setOrderState(new WaitValuate());
orderContext.Handle(Active.ACTIVE_VALUATE);
orderContext.setOrderState(new Finished());
orderContext.Handle(Active.ACTIVE_VALUATE);
}
}
OrderState实现:
/**
* @Author dingws
* @PackageName JavaStudy
* @Package org.goodStudy.designPattern.stateMode
* @Date 2021/11/2 2:15 下午
* @Version 1.0
*/
public class OrderState {
protected State state = State.FINISHED;
void OrderState(){
state = State.FINISHED;
}
public void Handle(Active active){
}
}
class WaitPay extends OrderState {
@Override
public void Handle(Active active){
if (active == Active.ACTIVE_PAY){
System.out.println("用户已付款,等待发货");
this.state = State.WAIT_SEND;
} else if (active == Active.ACTIVE_CACLE) {
this.state = State.FINISHED;
} else {
System.out.println("等待用户支付,当前订单状态为:" + state.getName());
}
}
}
class WaitSend extends OrderState {
@Override
public void Handle(Active active){
if (active == Active.ACTIVE_SEND){
System.out.println("卖家已发货,等待订单签收");
this.state = State.WAIT_RECV;
} else {
System.out.println("等待卖家发货,当前订单状态为:" + state.getName());
}
}
}
class WaitRecv extends OrderState {
@Override
public void Handle(Active active){
if (active == Active.ACTIVE_RECV){
System.out.println("订单已签收,等待用户评价");
this.state = State.WAIT_VALUATE;
} else if (active == Active.ACTIVE_CACLE) {
if (state == State.WAIT_SEND){
System.out.println("商品未发货,取消订单成功");
this.state = State.FINISHED;
} else {
System.out.println("商品未发货,取消订单失败");
}
} else {
System.out.println("等待用户签收订单,当前订单状态为:" + state.getName());
}
}
}
class WaitValuate extends OrderState {
@Override
public void Handle(Active active){
if (active == Active.ACTIVE_VALUATE){
System.out.println("用户已评价,订单关闭");
this.state = State.FINISHED;
} else {
System.out.println("等待卖家发货,当前订单状态为:" + state.getName());
}
}
}
class Finished extends OrderState{
@Override
public void Handle(Active active){
if (state == State.FINISHED){
System.out.println("订单已完成");
} else {
System.out.println("等待订单完成,当前订单状态为:" + state.getName());
}
}
}
参考链接:
https://blog.csdn.net/qq_33000453/article/details/106749593
http://c.biancheng.net/view/1388.html
http://c.biancheng.net/view/8492.html