問題場景:
對於一個訂單在不同的階段有不同的狀態,不同的狀態處理邏輯也不一樣。如果使用if/esle來判斷訂單狀態,從而實現不同的操作。這樣難以應對變化,增加一個狀態,我們就需要增加一個分之,還可能影響原有邏輯判斷。
if(待支付){
xxx
}else if(已付款){
xxxx
}else if(代發貨){
xxxx
}else if(已發貨){
xxxx
}
......
狀態模式主要用來解決對象在多種狀態轉換時,需要對外 輸出不同的行為的問題。狀態和行為是一一對應的,狀態之間可以相互轉換。
在狀態模式中,我們需要創建表示各種狀態的對象和一個行為隨着狀態對象改變而改變的 context 對象。
比如上述訂單的各種狀態:待付款,已付款,待發貨,已發貨,已簽收等。
按照狀態模式來設計,首先創建一個State接口以及他的各種實現,每個實現類對於接口的抽象方法都有不同的處理邏輯,並且根據具體的業務流程會修改Context對象里面的狀態。Context類聚合State並且與State的實現相互關聯。
類圖如下:
基於此類圖實現代碼:
--------------
狀態:
State:
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public abstract class State { abstract void pay(); abstract void checkPay(); abstract void deliverGoods(); abstract void toBeReceive(); abstract void receive(); abstract void other(); }
ToBePayState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class ToBePayState extends State { private OrderContext orderContext; public ToBePayState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { System.out.println("用戶已支付..."); orderContext.setState(orderContext.getPaidState()); } @Override void checkPay() { } @Override void deliverGoods() { System.out.println("未付款,不能發貨"); } @Override void toBeReceive() { } @Override void receive() { } @Override void other() { } }
PaidState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class PaidState extends State { private OrderContext orderContext; public PaidState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { System.out.println("已支付"); } @Override void checkPay() { System.out.println("確認支付成功..."); orderContext.setState(orderContext.getDeliverGoodsState()); } @Override void deliverGoods() { System.out.println("准備發貨"); } @Override void toBeReceive() { } @Override void receive() { } @Override void other() { } }
DeliverGoodsState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class DeliverGoodsState extends State { private OrderContext orderContext; public DeliverGoodsState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { System.out.println("已支付"); } @Override void checkPay() { } @Override void deliverGoods() { System.out.println("物流發貨..."); orderContext.setState(orderContext.getGoodsReceivedState()); } @Override void toBeReceive() { } @Override void receive() { } @Override void other() { } }
GoodsToBeReceivedState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class GoodsToBeReceivedState extends State { private OrderContext orderContext; public GoodsToBeReceivedState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { } @Override void checkPay() { } @Override void deliverGoods() { } @Override void toBeReceive() { System.out.println("運輸中..."); orderContext.setState(orderContext.getGoodsReceivedState()); } @Override void receive() { } @Override void other() { } }
GoodsReceivedState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class GoodsReceivedState extends State { private OrderContext orderContext; public GoodsReceivedState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { } @Override void checkPay() { } @Override void deliverGoods() { } @Override void toBeReceive() { } @Override void receive() { System.out.println("簽收貨物..."); orderContext.setState(orderContext.getSuccessState()); } @Override void other() { } }
SuccessState
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class SuccessState extends State { private OrderContext orderContext; public SuccessState(OrderContext orderContext) { this.orderContext = orderContext; } @Override void pay() { System.out.println("已支付"); } @Override void checkPay() { } @Override void deliverGoods() { System.out.println("已收貨"); } @Override void toBeReceive() { } @Override void receive() { } @Override void other() { System.out.println("用戶積分增加..."); } }
--------------
context
OrderContext
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class OrderContext { private State state; private ToBePayState toBePayState = new ToBePayState(this); private PaidState paidState = new PaidState(this); private DeliverGoodsState deliverGoodsState = new DeliverGoodsState(this); private GoodsToBeReceivedState goodsToBeReceivedState = new GoodsToBeReceivedState(this); private GoodsReceivedState goodsReceivedState = new GoodsReceivedState(this); private SuccessState successState = new SuccessState(this); //初始化訂單的時候狀態設置待付款 public OrderContext(String userName) { System.out.println("用戶 " + userName +" 下單"); this.state = toBePayState; } public void toPay(){ toBePayState.pay(); } public void checkPay(){ paidState.checkPay(); } public void deliverGoods(){ deliverGoodsState.deliverGoods(); } public void toBeReceive(){ goodsToBeReceivedState.toBeReceive(); } public void receive(){ goodsReceivedState.receive(); } public void end(){ successState.other(); } public State getState() { return state; } public void setState(State state) { this.state = state; } public ToBePayState getToBePayState() { return toBePayState; } public void setToBePayState(ToBePayState toBePayState) { this.toBePayState = toBePayState; } public PaidState getPaidState() { return paidState; } public void setPaidState(PaidState paidState) { this.paidState = paidState; } public DeliverGoodsState getDeliverGoodsState() { return deliverGoodsState; } public void setDeliverGoodsState(DeliverGoodsState deliverGoodsState) { this.deliverGoodsState = deliverGoodsState; } public SuccessState getSuccessState() { return successState; } public void setSuccessState(SuccessState successState) { this.successState = successState; } public GoodsToBeReceivedState getGoodsToBeReceivedState() { return goodsToBeReceivedState; } public void setGoodsToBeReceivedState(GoodsToBeReceivedState goodsToBeReceivedState) { this.goodsToBeReceivedState = goodsToBeReceivedState; } public GoodsReceivedState getGoodsReceivedState() { return goodsReceivedState; } public void setGoodsReceivedState(GoodsReceivedState goodsReceivedState) { this.goodsReceivedState = goodsReceivedState; } }
測試:
package com.nijunyang.designpatterns.state; /** * @author: create by nijunyang * @date:2019/9/22 */ public class Test { public static void main(String[] args) throws InterruptedException { for(int i = 0; i < 5; i++) { OrderContext orderContext = new OrderContext("user" + i); orderContext.toPay(); orderContext.checkPay(); orderContext.deliverGoods(); orderContext.toBeReceive(); orderContext.receive(); orderContext.end(); System.out.println("---------"); Thread.sleep(1000); } } }
以上代碼的實現都是按照最簡單的正常流程走的,實際上,不同State的實現類里面不同的方法還會操作修改狀態,這個就要根據實際的業務流程來控制了。
簡單總結:
使用狀態模式代碼有很強的可讀性。狀態模式將每個狀態的行為封裝到對應的一個類中方便維護。
減少if/else。符合“開閉原則”。容易增刪狀態。
但是會產生很多類,每個狀態都要一個對應的類,當狀態過多時會產生很多類,加大維護成本。
當一個事件或者對象有很多種狀態,狀態之間會相互轉換,對不同的狀態要求有不同的行為的時候,可以考慮使用狀態模式