Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
很多人會(huì)問(wèn)我店鋪申請(qǐng)刪單之后,店鋪分?jǐn)?shù)就被扣完了,導(dǎo)致店鋪只能暫時(shí)性關(guān)閉,那么這就是犯了常見的錯(cuò)誤。京東刪單是商家由于各種原因向后臺(tái)提出刪單申請(qǐng),刪除訂單可以更好的保障店鋪運(yùn)營(yíng)基本不受影響。但是具體哪些情況下能刪單,刪單時(shí)會(huì)遇到哪些疑問(wèn),這些都是很大問(wèn)題。都知道當(dāng)遇到批量下單、敲詐勒索、差價(jià)/運(yùn)費(fèi)/贈(zèng)品鏈接、套取利益這四類場(chǎng)景情況時(shí),自然能提交異常訂單刪除。如果不是這些情況,還能有什么方法刪單呢。
1、除京東異常刪單,還有什么情況能刪單?
還有一種情況是協(xié)商刪單,這種僅限貨到付款訂單。使用場(chǎng)景有4種,下面分別舉例。
第一種,商家聯(lián)系客戶,客戶同意取消訂單。例如商品脫銷/超賣/有瑕疵,商家可預(yù)先聯(lián)系客戶解釋,征得客戶同意的前提下,提交刪單申請(qǐng),并注明刪單原因。第二種,商家聯(lián)系客戶,客戶同意取消訂單。例如:貨到付款訂單用戶拒收,賣家聯(lián)系用戶,確認(rèn)商品拒收取消后提交刪單申請(qǐng)。第三種,聯(lián)系不上客戶或客戶同意取消訂單。例如:用戶下單不符合購(gòu)買規(guī)則或地址不詳無(wú)法配送,商家聯(lián)系用戶確認(rèn)訂單異常點(diǎn),是否可以修改訂單,如無(wú)法修改是否同意取消訂單。第四種,客戶要求取消訂單。例如:用戶原因取消訂單申請(qǐng)刪單,用戶通過(guò)咚咚/400電話聯(lián)系商家告知要求取消訂單。
2、京東協(xié)商刪單具體怎么操作?
具體操作路徑:權(quán)益服務(wù) >維權(quán)管理>刪單申請(qǐng) > 協(xié)商刪單>添加刪單。
3、申請(qǐng)京東刪單后,訂單多久之后就會(huì)刪除?
商家提交刪單申請(qǐng)后,系統(tǒng)自動(dòng)觸發(fā)短信至消費(fèi)者,告知訂單已被申請(qǐng)刪除。如消費(fèi)者反饋未與商家達(dá)成一致,則刪單申請(qǐng)被駁回;如消費(fèi)者未提出異議,訂單在48小時(shí)后自動(dòng)刪除。
4、京東惡意訂單申請(qǐng)刪單記錄在哪里查?
商家登錄商家后臺(tái)—權(quán)益服務(wù)—維權(quán)管理—申請(qǐng)刪單—異常刪單/協(xié)商刪單內(nèi),默認(rèn)展示申請(qǐng)刪單歷史記錄,或者您也可以選擇對(duì)應(yīng)的篩選框選項(xiàng)進(jìn)行查詢。
5、違規(guī)申請(qǐng)刪單,平臺(tái)將會(huì)給予哪種處罰?
對(duì)未經(jīng)消費(fèi)者同意申請(qǐng)協(xié)商刪單、遭消費(fèi)者投訴的的商家,平臺(tái)將按《京東開放平臺(tái)商家積分管理規(guī)則》中“違背承諾”進(jìn)行處理,每次扣12分。
ttps://v.qq.com/x/page/k3208z8fdh6.html
乘客取消訂單的原因有千千萬(wàn)
責(zé)任劃分怎么算
跟乘客溝通的過(guò)程很重要
有一些字眼千萬(wàn)不能說(shuō)
否則無(wú)責(zé)變有責(zé)
【那你取消吧】
但凡是你給乘客傳達(dá)出這樣的語(yǔ)句
那么一定是司機(jī)有責(zé)
而且!
乘客看到取消后要付空接費(fèi)后更不爽,隨便找個(gè)理由去投訴,結(jié)果服務(wù)分被扣了,你說(shuō)冤不冤呢?
還有一些情況,也屬于誘導(dǎo)乘客取消的行為
以下語(yǔ)句都會(huì)被判有責(zé)
以臨時(shí)有事為由
你好,我是咱們滴滴司機(jī),我要去吃飯呢,要不您換個(gè)車?
以車有問(wèn)題為由
你好,我是咱們滴滴司機(jī),我車出現(xiàn)一點(diǎn)問(wèn)題,不能去接您,要不您換個(gè)車?
以車有問(wèn)題為由而實(shí)際上車并沒問(wèn)題,這個(gè)理由也是不成立的。
以距離太遠(yuǎn)為由
你好,我是咱們滴滴司機(jī),我距離你那里太遠(yuǎn)了,你重新叫一輛車吧。
以堵車為由
你好,我是咱們滴滴司機(jī),這會(huì)兒很堵車,我過(guò)去接您估計(jì)要半個(gè)小時(shí),要不您重新叫一輛車?
要求加價(jià)
你好,我是滴滴司機(jī),我接你這一單不賺錢還得空跑回來(lái),你看我去接你的話能不能加一下空駛補(bǔ)償和過(guò)路費(fèi)。
所以,各位司機(jī)師傅們,溝通過(guò)程中
要【表達(dá)自己的接駕意愿】
不要【說(shuō)出誘導(dǎo)乘客取消訂單的話】
記住了嗎
skr~
態(tài)機(jī)簡(jiǎn)介:
狀態(tài)機(jī)是有限狀態(tài)自動(dòng)機(jī)的簡(jiǎn)稱,是現(xiàn)實(shí)事物運(yùn)行規(guī)則抽象而成的一個(gè)數(shù)學(xué)模型。【規(guī)則的抽象】
有限狀態(tài)機(jī)一般都有以下特點(diǎn):
(1)可以用狀態(tài)來(lái)描述事物,并且任一時(shí)刻,事物總是處于一種狀態(tài);
(2)事物擁有的狀態(tài)總數(shù)是有限的;
(3)通過(guò)觸發(fā)事物的某些行為,可以導(dǎo)致事物從一種狀態(tài)過(guò)渡到另一種狀態(tài);
(4)事物狀態(tài)變化是有規(guī)則的,A狀態(tài)可以變換到B,B可以變換到C,A卻不一定能變換到C;
(5)同一種行為,可以將事物從多種狀態(tài)變成同種狀態(tài),但是不能從同種狀態(tài)變成多種狀態(tài)。
狀態(tài)機(jī)這種描述客觀世界的方式就是將事物抽象成若干狀態(tài),然后所有的事件和規(guī)則導(dǎo)致事物在這些狀態(tài)中游走。最終使得事物“自圓其說(shuō)”。
很多通信協(xié)議的開發(fā)都必須用到狀態(tài)機(jī);一個(gè)健壯的狀態(tài)機(jī)可以讓你的程序,不論發(fā)生何種突發(fā)事件都不會(huì)突然進(jìn)入一個(gè)不可預(yù)知的程序分支。
四大概念:
狀態(tài)(state)
一個(gè)狀態(tài)機(jī)至少要包含兩個(gè)狀態(tài)。
分為:現(xiàn)態(tài)(源狀態(tài))、次態(tài)(目標(biāo)狀態(tài))
狀態(tài)可以理解為一種結(jié)果,一種穩(wěn)態(tài)形式,沒有擾動(dòng)會(huì)保持不變的。
狀態(tài)命名形式:
1.副詞+動(dòng)詞;例如:待審批、待支付、待收貨
這種命名方式體現(xiàn)了:狀態(tài)機(jī)就是事件觸發(fā)狀態(tài)不斷遷徙的本質(zhì)。表達(dá)一種待觸發(fā)的感覺。
2.動(dòng)詞+結(jié)果;例如:審批完成、支付完成
3.已+動(dòng)詞形式;例如:已發(fā)貨、已付款
以上兩種命名方式體現(xiàn)了:狀態(tài)是一種結(jié)果或者穩(wěn)態(tài)的本質(zhì)。表達(dá)了一種已完成的感覺。
角色很多的時(shí)候,為了表示清晰,可以加上角色名:例如:待財(cái)務(wù)審批、主管批準(zhǔn)
命名考慮從用戶的理解的角度出發(fā)。
事件(event)
or
觸發(fā)條件
又稱為“條件”,就是某個(gè)操作動(dòng)作的觸發(fā)條件或者口令。當(dāng)一個(gè)條件滿足時(shí),就會(huì)觸發(fā)一個(gè)動(dòng)作,或者執(zhí)行一次狀態(tài)遷徙
這個(gè)事件可以是外部調(diào)用、監(jiān)聽到消息、或者各種定時(shí)到期等觸發(fā)的事件。
對(duì)于燈泡,“打開開關(guān)”就是一個(gè)事件。
條件命名形式:動(dòng)詞+結(jié)果;例如:支付成功、下單時(shí)間>5分鐘
動(dòng)作(action)
事件發(fā)生以后要執(zhí)行動(dòng)作。例如:事件=“打開開關(guān)指令”,動(dòng)作=“開燈”。一般就對(duì)應(yīng)一個(gè)函數(shù)。
條件滿足后執(zhí)行動(dòng)作。動(dòng)作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。
動(dòng)作不是必需的,當(dāng)條件滿足后,也可以不執(zhí)行任何動(dòng)作,直接遷移到新狀態(tài)。
那么如何區(qū)分“動(dòng)作”和“狀態(tài)”?
“動(dòng)作”是不穩(wěn)定的,即使沒有條件的觸發(fā),“動(dòng)作”一旦執(zhí)行完畢就結(jié)束了;
而“狀態(tài)”是相對(duì)穩(wěn)定的,如果沒有外部條件的觸發(fā),一個(gè)狀態(tài)會(huì)一直持續(xù)下去。
變換(transition)
即從一個(gè)狀態(tài)變化到另外一個(gè)狀態(tài)
例如:“開燈過(guò)程”就是一個(gè)變化
狀態(tài)機(jī)其他表達(dá)方式:
狀態(tài)機(jī)的設(shè)計(jì):
信息系統(tǒng)中有很多狀態(tài)機(jī),例如:業(yè)務(wù)訂單的狀態(tài)。
狀態(tài)機(jī)的設(shè)計(jì)存在的問(wèn)題:什么是狀態(tài)?到底有多少個(gè)狀態(tài)?要細(xì)分到什么程度?
信息系統(tǒng)是現(xiàn)實(shí)世界的一種抽象和描述。而業(yè)務(wù)領(lǐng)域中那些已經(jīng)發(fā)生的事件就是事實(shí),信息系統(tǒng)就是將這些事實(shí)以信息的形式存儲(chǔ)到數(shù)據(jù)庫(kù)中,即:信息就是一組事實(shí)
信息系統(tǒng)就是存儲(chǔ)這些事實(shí),對(duì)這些事實(shí)進(jìn)行管理與追蹤,進(jìn)而起到提高工作效率的作用。
信息系統(tǒng)就是記錄已經(jīng)發(fā)生的事實(shí),信息系統(tǒng)中的狀態(tài)基本和事實(shí)匹配。即:標(biāo)識(shí)某個(gè)事實(shí)的完成度。
業(yè)務(wù)系統(tǒng),根據(jù)實(shí)際業(yè)務(wù),具體會(huì)有哪些發(fā)生的事實(shí)需要記錄,基本上這些事實(shí)就至少對(duì)應(yīng)一個(gè)狀態(tài)。需要記錄的事實(shí)就是一種穩(wěn)態(tài),一種結(jié)果。
例如:【待支付】->【已支付】->【已收貨】->【已評(píng)價(jià)】
這些都是系統(tǒng)需要記錄的已發(fā)生的客觀事實(shí)。而這些事實(shí)就對(duì)應(yīng)了狀態(tài),而發(fā)生這些事實(shí)的事件就對(duì)應(yīng)了觸發(fā)狀態(tài)機(jī)的轉(zhuǎn)換的事件。
根據(jù)自己的業(yè)務(wù)實(shí)際進(jìn)行分析,并畫出狀態(tài)圖即可。
狀態(tài)機(jī)實(shí)現(xiàn)方式:狀態(tài)模式
下面是經(jīng)典的自動(dòng)販賣機(jī)例子來(lái)說(shuō)明狀態(tài)模式的用法,狀態(tài)圖如下:
分析一個(gè)這個(gè)狀態(tài)圖:
a、包含4個(gè)狀態(tài)(我們使用4個(gè)int型常量來(lái)表示)
b、包含3個(gè)暴露在外的方法(投幣、退幣、轉(zhuǎn)動(dòng)手柄、(發(fā)貨動(dòng)作是內(nèi)部方法,售賣機(jī)未對(duì)外提供方法,售賣機(jī)自動(dòng)調(diào)用))
c、我們需要處理每個(gè)狀態(tài)下,用戶都可以觸發(fā)這三個(gè)動(dòng)作。
我們可以做沒有意義的事情,在【未投幣】狀態(tài),試著退幣,或者同時(shí)投幣兩枚,此時(shí)機(jī)器會(huì)提示我們不能這么做。
實(shí)現(xiàn)邏輯:
任何一個(gè)可能的動(dòng)作,我們都要檢查,看看我們所處的狀態(tài)和動(dòng)作是否合適。
狀態(tài)機(jī)使用if-else或switch實(shí)現(xiàn)
測(cè)試自動(dòng)售賣機(jī)
使用if-else/switch的方式實(shí)現(xiàn)狀態(tài)有如下問(wèn)題:
例如:現(xiàn)在增加一個(gè)狀態(tài)。每個(gè)方法都需要添加if-else語(yǔ)句。
升級(jí)策略:
【封裝變化】,局部化每個(gè)狀態(tài)的行為,將每個(gè)狀態(tài)的行為放到各自類中,每個(gè)狀態(tài)只要實(shí)現(xiàn)自己的動(dòng)作就可以了。
販賣機(jī)只要將動(dòng)作委托給代表當(dāng)前狀態(tài)的狀態(tài)對(duì)象即可。
public interface State
{
/**
* 放錢
*/
public void insertMoney();
/**
* 退錢
*/
public void backMoney();
/**
* 轉(zhuǎn)動(dòng)曲柄
*/
public void turnCrank();
/**
* 出商品
*/
public void dispense();
}
public class NoMoneyState implements State
{
private VendingMachine machine;
public NoMoneyState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
System.out.println("投幣成功");
machine.setState(machine.getHasMoneyState());
}
@Override
public void backMoney()
{
System.out.println("您未投幣,想退錢?...");
}
@Override
public void turnCrank()
{
System.out.println("您未投幣,想拿東西么?...");
}
@Override
public void dispense()
{
throw new IllegalStateException("非法狀態(tài)!");
}
}
public class HasMoneyState implements State
{
private VendingMachine machine;
public HasMoneyState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
System.out.println("您已經(jīng)投過(guò)幣了,無(wú)需再投....");
}
@Override
public void backMoney()
{
System.out.println("退幣成功");
machine.setState(machine.getNoMoneyState());
}
@Override
public void turnCrank()
{
System.out.println("你轉(zhuǎn)動(dòng)了手柄");
machine.setState(machine.getSoldState());
}
@Override
public void dispense()
{
throw new IllegalStateException("非法狀態(tài)!");
}
}
public class SoldOutState implements State
{
private VendingMachine machine;
public SoldOutState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
System.out.println("投幣失敗,商品已售罄");
}
@Override
public void backMoney()
{
System.out.println("您未投幣,想退錢么?...");
}
@Override
public void turnCrank()
{
System.out.println("商品售罄,轉(zhuǎn)動(dòng)手柄也木有用");
}
@Override
public void dispense()
{
throw new IllegalStateException("非法狀態(tài)!");
}
}
public class SoldState implements State
{
private VendingMachine machine;
public SoldState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
System.out.println("正在出貨,請(qǐng)勿投幣");
}
@Override
public void backMoney()
{
System.out.println("正在出貨,沒有可退的錢");
}
@Override
public void turnCrank()
{
System.out.println("正在出貨,請(qǐng)勿重復(fù)轉(zhuǎn)動(dòng)手柄");
}
@Override
public void dispense()
{
machine.releaseBall();
if (machine.getCount() > 0)
{
machine.setState(machine.getNoMoneyState());
} else
{
System.out.println("商品已經(jīng)售罄");
machine.setState(machine.getSoldOutState());
}
}
}
public class VendingMachine
{
private State noMoneyState;
private State hasMoneyState;
private State soldState;
private State soldOutState;
private State winnerState ;
private int count=0;
private State currentState=noMoneyState;
public VendingMachine(int count)
{
noMoneyState=new NoMoneyState(this);
hasMoneyState=new HasMoneyState(this);
soldState=new SoldState(this);
soldOutState=new SoldOutState(this);
winnerState=new WinnerState(this);
if (count > 0)
{
this.count=count;
currentState=noMoneyState;
}
}
//將這些動(dòng)作委托給當(dāng)前狀態(tài).
public void insertMoney()
{
currentState.insertMoney();
}
public void backMoney()
{
currentState.backMoney();
}
// 機(jī)器不用提供dispense動(dòng)作,因?yàn)檫@是一個(gè)內(nèi)部動(dòng)作.用戶不可以直
//接要求機(jī)器發(fā)放糖果.我們?cè)跔顟B(tài)對(duì)象的turnCrank()方法中調(diào)用
//dispense方法;
//dispense無(wú)論如何,即使在nomoney狀態(tài)也會(huì)被執(zhí)行.
//讓不合法的情形下,dispense拋出異常處理。
public void turnCrank()
{
currentState.turnCrank();
currentState.dispense();
}
public void releaseBall()
{
System.out.println("發(fā)出一件商品...");
if (count !=0)
{
count -=1;
}
}
public void setState(State state)
{
this.currentState=state;
}
//getter setter omitted ...
}
我們之前說(shuō)過(guò),if-else/switch實(shí)現(xiàn)方式?jīng)]有彈性,那現(xiàn)在按照這種實(shí)現(xiàn)模式,需求變更修改起來(lái)會(huì)輕松點(diǎn)嗎?
紅色部分標(biāo)記了我們的需求變更:當(dāng)用戶每次轉(zhuǎn)動(dòng)手柄的時(shí)候,有10%的幾率贈(zèng)送一瓶。
實(shí)現(xiàn)方式:
我們遵守了【開閉】原則,只要新建一個(gè)WinnerState的類即可。然后有限的修改has_money的轉(zhuǎn)向即可。
為什么WinnerState要獨(dú)立成一個(gè)狀態(tài),其實(shí)它和sold狀態(tài)一模一樣。我把代碼寫在SoldState中不行嗎?
如果sold需求變化不一定影響到winner代碼實(shí)現(xiàn),winner需求變化時(shí),也不一定要修改sold,比如促銷方案結(jié)束了,中獎(jiǎng)概率變了等。
如果他們的變化不是一定互相影響到彼此的,那我們就該將他們分離,即是【隔離變化】也是遵守【單一職責(zé)】的原則。
public class WinnerState implements State
{
private VendingMachine machine;
public WinnerState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
throw new IllegalStateException("非法狀態(tài)");
}
@Override
public void backMoney()
{
throw new IllegalStateException("非法狀態(tài)");
}
@Override
public void turnCrank()
{
throw new IllegalStateException("非法狀態(tài)");
}
@Override
public void dispense()
{
System.out.println("你中獎(jiǎng)了,恭喜你,將得到2件商品");
machine.releaseBall();
if (machine.getCount()==0)
{
System.out.println("商品已經(jīng)售罄");
machine.setState(machine.getSoldOutState());
} else
{
machine.releaseBall();
if (machine.getCount() > 0)
{
machine.setState(machine.getNoMoneyState());
} else
{
System.out.println("商品已經(jīng)售罄");
machine.setState(machine.getSoldOutState());
}
}
}
}
public class HasMoneyState implements State
{
private VendingMachine machine;
private Random random=new Random();
public HasMoneyState(VendingMachine machine)
{
this.machine=machine;
}
@Override
public void insertMoney()
{
System.out.println("您已經(jīng)投過(guò)幣了,無(wú)需再投....");
}
@Override
public void backMoney()
{
System.out.println("退幣成功");
machine.setState(machine.getNoMoneyState());
}
@Override
public void turnCrank()
{
System.out.println("你轉(zhuǎn)動(dòng)了手柄");
int winner=random.nextInt(10);
if (winner==0 && machine.getCount() > 1)
{
machine.setState(machine.getWinnerState());
} else
{
machine.setState(machine.getSoldState());
}
}
@Override
public void dispense()
{
throw new IllegalStateException("非法狀態(tài)!");
}
}
總結(jié)狀態(tài)模式:
狀態(tài)模式:允許對(duì)象在內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來(lái)好像修改了他的類。
解釋:
狀態(tài)模式將狀態(tài)封裝成為獨(dú)立的類,并將動(dòng)作委托到代表當(dāng)前狀態(tài)的對(duì)象。
所以行為會(huì)隨著內(nèi)部狀態(tài)改變而改變。
我們通過(guò)組合簡(jiǎn)單引用不同狀態(tài)對(duì)象來(lái)造成類改變的假象.
狀態(tài)模式策略模式
1.行為封裝的n個(gè)狀態(tài)中,不同狀態(tài)不用行為。
2.context的行為委托到不同狀態(tài)中。
3.[當(dāng)前狀態(tài)]在n個(gè)狀態(tài)中游走,context的行為也隨之[當(dāng)前狀態(tài)]的改變而改變。
4.用戶對(duì)context的狀態(tài)改變渾然不知。
5.客戶不會(huì)直接和state交互,只能通過(guò)context暴露的方法交互,state轉(zhuǎn)換是context內(nèi)部事情。
6.state可以是接口也可以是抽象類,取決于有沒公共功能可以放進(jìn)抽象類中。抽象類方便,因?yàn)榭梢院罄m(xù)加方法。
可以將重復(fù)代碼放入抽象類中。例如:"你已投入25元,不能重復(fù)投" 這種通用代碼放入抽象類中。
7.context可以決定狀態(tài)流轉(zhuǎn),如果這個(gè)狀態(tài)流轉(zhuǎn)是固定的,就適合放在context中進(jìn)行。但是如果狀態(tài)流轉(zhuǎn)是動(dòng)態(tài)的就適合放在狀態(tài)中進(jìn)行。
例如通過(guò)商品的剩余數(shù)目來(lái)決定流向[已售完]或[等待投幣],這個(gè)時(shí)候放在狀態(tài)類中,因?yàn)閐ispense要根據(jù)狀態(tài)判斷流轉(zhuǎn)。
這個(gè)寫法決定了,有新需求時(shí)候,你是改context還是改state類。
8.可以共享所有的state對(duì)象,但是需要修改context的時(shí)候時(shí)候,需要handler中傳入context引用
1.context主動(dòng)指定需要組合的策略對(duì)象是哪一個(gè)。
2.可以在啟動(dòng)的時(shí)候通過(guò)工廠動(dòng)態(tài)指定具體是哪個(gè)策略對(duì)象,但是沒有在策略對(duì)象之間游走,即:只組合了一個(gè)策略對(duì)象。
3.策略作為繼承之外一種彈性替代方案。因?yàn)槔^承導(dǎo)致子類繼承不適用的方法,且每個(gè)類都要維護(hù),策略模式通過(guò)不同對(duì)象組合來(lái)改變行為。
4.策略模式聚焦的是互換的算法來(lái)創(chuàng)建業(yè)務(wù)。
狀態(tài)機(jī)典型應(yīng)用:訂單狀態(tài)控制
建表語(yǔ)句
如上圖所示:
一種典型的訂單設(shè)計(jì)。業(yè)務(wù)訂單和支付退款訂單組合,他們分別有自己的狀態(tài)機(jī)。
狀態(tài)機(jī)模式實(shí)現(xiàn)訂單狀態(tài)機(jī):
日常開發(fā)過(guò)程中,狀態(tài)機(jī)模式應(yīng)用場(chǎng)景之一的就是訂單模型中的狀態(tài)控制。但是區(qū)別于狀態(tài)模式的點(diǎn)有以下幾個(gè):
以支付訂單為例:
/*
Title: PaymentInfo Description:
支付訂單狀態(tài)機(jī)
該類不可被spring管理,需要new出來(lái),一個(gè)類就對(duì)應(yīng)一條數(shù)據(jù)庫(kù)中支付訂單記錄
本文來(lái)自博客園,作者:wanglifeng,轉(zhuǎn)載請(qǐng)注明原文鏈接:https://www.cnblogs.com/wanglifeng717/p/16214122.html
@author wanglifeng
*/
public class PaymentStateMachine {
// 數(shù)據(jù)庫(kù)中當(dāng)前支付訂單實(shí)體
private SapoPayment payment;
// 當(dāng)前狀態(tài)
private PaymentState currentState;
// 需要更新入庫(kù)的支付訂單實(shí)體。與payment屬性配合,payment為當(dāng)前數(shù)據(jù)庫(kù)中訂單實(shí)體,用于樂觀鎖的前置內(nèi)容校驗(yàn)。
private SapoPayment paymentForUpdate;
/* 將最新內(nèi)容(含狀態(tài))更新入庫(kù),并當(dāng)前狀態(tài)機(jī)狀態(tài) */
public void updateStateMachine() {
// 從Spring容器中獲取操作數(shù)據(jù)的dao
SapoDao dao=SpringUtil.getBean(SapoDao.class);
// 更新數(shù)據(jù)庫(kù),樂觀鎖機(jī)制:帶前置內(nèi)容數(shù)據(jù)校驗(yàn),其中payment為前置內(nèi)容,paymentForUpdate為要更新的內(nèi)容,如果更新結(jié)果=0,說(shuō)明該訂單被其他線程修改過(guò)。拋異常,放棄此次修改。
dao.updateSapoPaymentByNull(paymentForUpdate, payment);
// 記錄訂單操作流水
dao.insertSapoOrderStatusLog(SapoOrderStatusLog.getInstance().setOrderId(paymentForUpdate.getId())
.setOrderType(SapoOrderStatusLog.ORDER_TYPE_PAYMENT).setStatus(paymentForUpdate.getStatus()));
// 更新當(dāng)前PaymentStateMachine狀態(tài)機(jī)
this.setPayment(paymentForUpdate);
this.setCurrentState(paymentForUpdate.getStatus());
}
// 通過(guò)條件獲取一個(gè)支付訂單PaymentStateMachine實(shí)體
public static PaymentStateMachine getInstance(SapoPayment sapoPaymentForQuery) {
// 1.從spring容器中獲取dao;
SapoDao dao=SpringUtil.getBean(SapoDao.class);
// 2.查出該支付訂單
SapoPayment paymentResult=dao.getSapoPayment(sapoPaymentForQuery);
// 3.初始化訂單狀態(tài)機(jī)
PaymentStateMachine paymentStateMachine=new PaymentStateMachine();
paymentStateMachine.setPayment(paymentResult);
paymentStateMachine.setCurrentState(paymentResult.getStatus());
paymentStateMachine.setPaymentForUpdate(SapoPayment.getInstance(paymentResult));
return paymentStateMachine;
}
// 設(shè)置當(dāng)前狀態(tài)機(jī)的狀態(tài)。輸入數(shù)據(jù)庫(kù)中status字段,映射成對(duì)應(yīng)的狀態(tài)類實(shí)體。
public void setCurrentState(Integer status) {
PaymentState currentState=null;
// status數(shù)字,映射成對(duì)應(yīng)的狀態(tài)類實(shí)體
if (SapoPayment.STATUS_APPLY.equals(status)) {
currentState=SpringUtil.getBean(PaymentStateApply.class);
} else if (SapoPayment.STATUS_WAIT_PAY.equals(status)) {
currentState=SpringUtil.getBean(PaymentStateWaitPay.class);
} else if (SapoPayment.STATUS_PAY_FINISH.equals(status)) {
currentState=SpringUtil.getBean(PaymentStatePayFinish.class);
} else if (SapoPayment.STATUS_FAIL.equals(status)) {
currentState=SpringUtil.getBean(PaymentStateFail.class);
} else if (SapoPayment.STATUS_CANCEL.equals(status)) {
currentState=SpringUtil.getBean(PaymentStateCancel.class);
} else {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(),
"status not in state machine ,status: " + status);
}
this.currentState=currentState;
}
// TODO 待實(shí)現(xiàn),申請(qǐng)支付訂單
public void apply() {
// 委托給當(dāng)前狀態(tài)執(zhí)行,將當(dāng)前訂單狀態(tài)機(jī)對(duì)象傳進(jìn)去,使用狀態(tài)對(duì)象處理訂單
currentState.apply(this);
}
// TODO 待實(shí)現(xiàn),通知支付結(jié)果
public void resultNotify() {
// 委托給當(dāng)前狀態(tài)執(zhí)行
currentState.resultNotify(this);
}
// TODO 同步給當(dāng)前狀態(tài)執(zhí)行
public void sync() {
// 委托給當(dāng)前狀態(tài)執(zhí)行
currentState.sync(this);
}
// 取消訂單
public void cancel() {
// 委托給當(dāng)前狀態(tài)執(zhí)行
currentState.cancel(this);
}
}
public interface PaymentState {
public void apply(PaymentStateMachine paymentStateMachine);
public void resultNotify(PaymentStateMachine paymentStateMachine);
public void sync(PaymentStateMachine paymentStateMachine);
public void cancel(PaymentStateMachine paymentStateMachine);
}
@Service
public class PaymentStateApply extends BaseLogger implements PaymentState {
@Autowired
FmPayClientService fmPayClientService;
@Autowired
SapoDao dao;
@Autowired
private JacksonComponent jacksonComponent;
public void apply(PaymentStateMachine paymentStateMachine) {
}
public void sync(PaymentStateMachine paymentStateMachine) {
}
public void resultNotify(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void cancel(PaymentStateMachine paymentStateMachine) {
SapoPayment sapoPaymentForUpdate=paymentStateMachine.getPaymentForUpdate();
sapoPaymentForUpdate.setStatus(SapoPayment.STATUS_CANCEL);
sapoPaymentForUpdate.setExpireTime(null);
paymentStateMachine.updateStateMachine();
}
}
@Service
public class PaymentStateCancel extends BaseLogger implements PaymentState {
public void apply(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void resultNotify(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void sync(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void cancel(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
}
@Service
public class PaymentStateFail extends BaseLogger implements PaymentState {
public void apply(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void resultNotify(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void sync(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void cancel(PaymentStateMachine paymentStateMachine) {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(), "fail status can not cancel");
}
}
@Service
public class PaymentStatePayFinish extends BaseLogger implements PaymentState {
public void apply(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void resultNotify(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void sync(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void cancel(PaymentStateMachine paymentStateMachine) {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(), "payfinish status can not cancel");
}
}
@Service
public class PaymentStateWaitPay extends BaseLogger implements PaymentState {
@Autowired
FmPayClientService fmPayClientService;
@Autowired
SapoDao dao;
@Autowired
private JacksonComponent jacksonComponent;
public void payResultNotify() {
// TODO implement here
}
public void apply(PaymentStateMachine paymentStateMachine) {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(),
"applyPayPlatform not match payment state machine,currentStatus:"
+ paymentStateMachine.getPayment().getStatus());
}
public void sync(PaymentStateMachine paymentStateMachine) {
// TODO 過(guò)期去統(tǒng)一支付查詢
String payStatus=queryPayResultResponse.getPayStatus();
// 1:初始化輸入 2:支付中 3:支付成功 4:支付失敗 5:撤銷
if (QueryPayResultResponse.PAY_STATUS_INIT.equals(payStatus)) {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(),
"FMpay queryPay return init status ,we are waitpay");
}
if (QueryPayResultResponse.PAY_STATUS_ING.equals(payStatus)) {
return;
}
SapoPayment sapoPaymentForUpdate=paymentStateMachine.getPaymentForUpdate();
if (QueryPayResultResponse.PAY_STATUS_CANCEL.equals(payStatus)) {
sapoPaymentForUpdate.setStatus(SapoPayment.STATUS_CANCEL);
} else if (QueryPayResultResponse.PAY_STATUS_FAIL.equals(payStatus)) {
sapoPaymentForUpdate.setStatus(SapoPayment.STATUS_FAIL);
} else if (QueryPayResultResponse.PAY_STATUS_SUCCESS.equals(payStatus)) {
sapoPaymentForUpdate.setStatus(SapoPayment.STATUS_PAY_FINISH);
}
sapoPaymentForUpdate.setExpireTime(null);
paymentStateMachine.updateStateMachine();
}
public void resultNotify(PaymentStateMachine paymentStateMachine) {
// TODO Auto-generated method stub
}
public void cancel(PaymentStateMachine paymentStateMachine) {
throw new BusinessException(ResultInfo.SYS_INNER_ERROR.getCode(), "wait pay status can not cancel");
}
}
文章來(lái)自https://www.cnblogs.com/wanglifeng717/p/16214122.html
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。