狀態(tài)模式允許其內(nèi)部狀態(tài)發(fā)生變化的時(shí)候改變其行為,貌似是對象改變了類。
一個(gè)對象的行為取決于一個(gè)或者多個(gè)動態(tài)變化的屬性,這些屬性叫做狀態(tài),比如訂單的支付狀態(tài);而這些訂單狀態(tài)的值是預(yù)先知道的,已支付、未支付;當(dāng)訂單在客戶操作過程中可能會改變支付狀態(tài),訂單從未支付到已支付,就形成訂單真正成功下單。
適用場景:
- 一個(gè)對象的行為取決于他的狀態(tài),并且它必須在運(yùn)行時(shí)根據(jù)狀態(tài)改變它的行為;
- 一個(gè)操作中含有龐大的多分支結(jié)構(gòu),并且這些分支決定于對象的狀態(tài)。
先看下 UML 類圖

上下文類Context: 維護(hù)一個(gè)ConcreteState子類的實(shí)例,這個(gè)實(shí)例定義當(dāng)前狀態(tài);
抽象狀態(tài)類State: 定義一個(gè)接口以封裝與Context的一個(gè)特定狀態(tài)相關(guān)的行為;
具體狀態(tài)類ConcreteState: 每一子類實(shí)現(xiàn)一個(gè)與Context的一個(gè)狀態(tài)相關(guān)的行為;
模擬下訂單的狀態(tài)改變:
總共有未支付、已支付、申請退款,退款中,退款完成訂單結(jié)束幾個(gè)過程,過程中每個(gè)狀態(tài)需要依賴上個(gè)狀態(tài),這個(gè)在本例中沒有做判斷,僅僅展示狀態(tài)變化的魔力。
首先把訂單狀態(tài)這個(gè)抽象類給寫出來
public abstract class OrderStatus {
protected Order order;
protected String name;
public OrderStatus(Order order,String name) {
this.order=order;
this.name=name;
}
public abstract OrderStatus next(Order order);
public void print(){
System.out.println("當(dāng)前狀態(tài)"+this.name);
}
}
然后把訂單類寫出
public class Order {
private OrderStatus status;
public OrderStatus getStatus() {
return status;
}
public void setStatus(OrderStatus status) {
this.status = status;
}
//other properties
}
他們之間是秤不離砣,你中有我,我中有你;
接下來看下具體的狀態(tài):
第一個(gè)是沒有支付的狀態(tài),也就是訂單默認(rèn)狀態(tài),甚至可以初始化到訂單內(nèi)部,這里也單獨(dú)拿出來
public class NoPayStatus extends OrderStatus{
public NoPayStatus(Order order,String name) {
super(order,name);
}
@Override
public OrderStatus next(Order order) {
print();
OrderStatus s=new PayStatus(order,"已支付");
order.setStatus(s);
return s;
}
}
第二,已支付狀態(tài)
public class PayStatus extends OrderStatus {
public PayStatus(Order order, String name) {
super(order, name);
}
@Override
public OrderStatus next(Order order) {
print();
return new ApplyDrawbackStatus(order, "申請退款");
}
}
第三是申請退款,第三部可以根據(jù)實(shí)際業(yè)務(wù)情況直接到第五狀態(tài)
public class ApplyDrawbackStatus extends OrderStatus {
public ApplyDrawbackStatus(Order order, String name) {
super(order, name);
}
@Override
public OrderStatus next(Order order) {
print();
return new DrawbackStatus(order, "訂單回款中");
}
}
第四是退款中
public class DrawbackStatus extends OrderStatus {
public DrawbackStatus(Order order, String name) {
super(order, name);
}
@Override
public OrderStatus next(Order order) {
print();
return new CompleteStatus(order, "訂單回款完成,徹底結(jié)束");
}
}
第五是訂單徹底完成
public class CompleteStatus extends OrderStatus {
public CompleteStatus(Order order, String name) {
super(order, name);
}
@Override
public OrderStatus next(Order order) {
print();
return null;
}
}
最后看下客戶端
public class Client {
public static void main(String[] args) {
Order order=new Order();
order.setStatus(new NoPayStatus(order, "未支付"));
OrderStatus status=order.getStatus();
status=status.next(order);
System.out.println("---------------");
status=status.next(order);
System.out.println("---------------");
status=status.next(order);
System.out.println("---------------");
status=status.next(order);
System.out.println("---------------");
status=status.next(order);
}
}
/** ----Result----
當(dāng)前狀態(tài)未支付
---------------
當(dāng)前狀態(tài)已支付
---------------
當(dāng)前狀態(tài)申請退款
---------------
當(dāng)前狀態(tài)訂單回款中
---------------
當(dāng)前狀態(tài)訂單回款完成,徹底結(jié)束
*/
客戶端需要校驗(yàn)空指針,這里不再贅述.
訂單狀態(tài)改變,也就是在 next 方法中需要做一些持久化操作和業(yè)務(wù)校驗(yàn),也許更加符合業(yè)務(wù)需要。