爲什麼使用命令模式大B:“上邊的代碼是否看起來很傻呢,本來可以這樣簡單實現的。”
publicclassClient{
publicstaticvoidmain(String[]args){
Receiverreceiver=newReceiver();
receiver.actionOne();
receiver.actionTwo();
}
}
publicclassReceiver{
publicReceiver(){
//
}
publicvoidactionOne(){
System.out.println(“ActionOnehasbeentaken.”);
}
publicvoidactionTwo(){
System.out.println(“ActionTwohasbeentaken.”);
}
}
大B:“看!多簡潔。如果是像上邊如此簡單的需求,這個才應該是我們的選擇,但是有些情況下這樣的寫法不能解決的,或者說解決起來不好,所以引入命令模式。1、我們須要Client和Receiver同時開發,而且在開發過程中分別須要不停重構,改名。2、如果我們要求Redo,Undo等功能。3、我們須要命令不按照調用執行,而是按照執行時的情況排序,執行。4、開發後期,我們發現必須要log哪些方法執行了,如何在儘量少更改代碼的情況下實現,並且漸少重複代碼。5、在上邊的情況下,我們的接受者有很多,不止一個。”
小A:“當我們遇到這些情況時應該怎樣去解決?”
大B:“解決辦法:情況一、我們可以定義一個接口,讓Receiver實現這個接口,Client按照接口調用。情況二、我們可以讓Receiver記住一些狀態,例如執行前的自己的狀態,用來undo,但自己記錄自己的狀態實現起來比較混亂,一般都是一個累記錄另一個類的狀態。情況三、很難實現。情況四、我們須要在每個Action,前後加上log。”情況五、相對好實現,但是再加上這個,是否感覺最終的實現很混亂呢?
大B:“好,我們再來看看命令模式,在命令模式中,我們增加一些過渡的類,這些類就是上邊的命名接口和命令實現,這樣就很好的解決了情況一、情況二。我們再加入一個Invoker,這樣情況三和情況四就比較好解決了。”
如下加入Log和排序後的。
publicclassInvoker{
privateListcmdList=newArrayList();
publicInvoker(){
}
publicadd(Commandmand){
cmdList.add(mand);
}
publicremove(Commandmand){
cmdList.remove(mand);
}
publicvoidaction(){
Commandcmd;
while((cmd=getCmd())!=null){
log(“begin”+cmd.getName());
cmd.execute();
log(“end”+cmd.getName());
}
}
publicCommandgetCmd(){
//按照自定義優先級,排序取出。
}
}
publicclassClient{
publicstaticvoidmain(String[]args){
Receiverreceiver=newReceiver();
CommandmandOne=newConcreteCommandOne(receiver);
CommandmandTwo=newConcreteCommandTwo(receiver);
Invokerinvoker=newInvoker();
invoker.add(mandOne);
invoker.add(mandTwo);
iinvoker.action();
}
}