问题场景:
对于一个订单在不同的阶段有不同的状态,不同的状态处理逻辑也不一样。如果使用if/esle来判断订单状态,从而实现不同的操作。这样难以应对变化,增加一个状态,我们就需要增加一个分之,还可能影响原有逻辑判断。
if(待支付){
xxx
}else if(已付款){
xxxx
}else if(代发货){
xxxx
}else if(已发货){
xxxx
}
......
状态模式的主要目的是: 当控制一个对象状态转换的条件表达式过于复杂时,把相关“判断逻辑”提取出来,放到一系列的状态类当中,这样可以把原来复杂的逻辑判断简单化。
比如上述订单的各种状态:待付款,已付款,待发货,已发货,已签收等,接下来对其进行实现:
/**
* 订单类
*/
public class OrderContext {
private State state;
//初始化订单的时候状态设置待付款
public OrderContext(String userName) {
System.out.println("用户 " + userName +" 下单");
this.state = new ToBePayState();
}
/**
* 进行下一个状态(例如待付款-->付款)
*/
public void doNext(){
state.doNext(this);
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}
/**
* 订单状态
*/
public interface State {
void doNext(OrderContext orderContext);
}
/**
* 待付款状态
*/
public class ToBePayState implements State{
@Override
public void doNext(OrderContext orderContext) {
System.out.println("付款成功!");
orderContext.setState(new PaidState());
}
}
/**
* 付款状态
*/
public class PaidState implements State{
@Override
public void doNext(OrderContext orderContext) {
System.out.println("运送中!");
orderContext.setState(new DeliverGoodsState());
}
}
/**
* 运送状态
*/
public class DeliverGoodsState implements State {
@Override
public void doNext(OrderContext orderContext) {
System.out.println("待签收!");
orderContext.setState(new GoodsToBeReceivedState());
}
}
/**
* 待签收状态
*/
public class GoodsToBeReceivedState implements State{
@Override
public void doNext(OrderContext orderContext) {
System.out.println("已签收!");
orderContext.setState(new GoodsReceivedState());
}
}
/**
* 已签收状态
*/
public class GoodsReceivedState implements State{
@Override
public void doNext(OrderContext orderContext) {
System.out.println("确认收货!");
orderContext.setState(new SuccessState());
}
}
/**
* 确认收货状态
*/
public class SuccessState implements State{
@Override
public void doNext(OrderContext orderContext) {
System.out.println("交易已完成,没有下一步了!");
}
}
public static void main(String[] args) {
OrderContext orderContext = new OrderContext("张三");
orderContext.doNext();
orderContext.doNext();
orderContext.doNext();
orderContext.doNext();
orderContext.doNext();
orderContext.doNext();
}
运行结果:
使用状态模式代码可以封装状态的转换规则,在状态模式中可以将状态的行为(转化)代码封装在具体状态类中,可以对状态转换代码进行集中管理,方便维护。
状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}