初衷:
看了一些命令模式的博客,仍然不知道如何實現一個命令模式,如何設計,以及爲何這麼設計,本文通過一個例子來說明命令模式的設計過程以及這麼設計的原因。
命令模式分解:
命令模式從組成上分爲:
- 命令(Command)
- 調用者 (invoker)
- 客戶端 (client)
- 命令接收者 (receiver)
其中,命令的具體實現類可以有多個,即可以有多個命令。
調用者爲統一處理命令,讓命令接收者執行命令,只有一個。
客戶端爲發起命令的主體。
命令接收者爲具體的命令執行者。
接下來,我們看看具體的例子來理解何爲命令模式,如何設計。
eg:PM要給RD提出各種各樣的需求和修改,但需要在需求評審會上進行需求評審,由Leader拍板是不是做,PM說,RD,請實現APP的界面顏色隨着用戶手機殼顏色的變化而變化,Leader一聽,有意思,做起來,然後給RD下達了命令,RD一看需求無能爲力,將無法實現的結果告訴Leader,Leader將最終結果反饋給PM。
在這個例子中,PM(客戶端)發出了命令,命令包括了兩部分內容:
- RD(命令的接收者)
- APP界面顏色隨着手機殼顏色變化而變化(接收者需要做的具體操作)
然後PM(客戶端)不直接去找RD(receiver),需要找Leader(invoker)進行需求評審,Leader(invoker)需要作出一些判斷或者前置後置處理,再讓RD(接收者)執行具體的命令。
如何設計命令模式
這就是一個命令模式的例子,通過例子我們可以思考,如何設計命令模式:
參考上述命令模式的組成,我們分別設計:
設計命令:
有例子可以看出,一個具體的命令包括了具體的命令接收者和具體的執行操作,又由於可以有很多個命令,所以需要將命令進行抽象化,即接口或者抽象類:
public abstract class Command {
//每個命令類都必須有一個執行命令的方法
public abstract void execute();
}
具體的命令類需要包括兩個部分,一是實現抽象類的方法,即命令的具體操作,二是新增命令的執行者屬性。
public class ConcreteCommand extends Command {
//對哪個Receiver類進行命令處理
private Receiver receiver;
//構造函數傳遞接收者
public ConcreteCommand(Receiver _receiver){
this.receiver = _receiver;
}
//必須實現一個命令
public void execute() {
//業務處理
this.receiver.doSomething();
}
}
設計調用者:
根據上述的Leader(invoker),他需要知道PM的具體命令,所以他需要有一個命令的成員變量,然後他需要經過一些操作後讓RD(接收者)開始執行命令,所以他一個執行方法。
public class Invoker {
private Command command;
//設置命令
public void setCommand(Command _command){
this.command = _command;
}
//執行命令
public void action(){
this.command.execute();
}
}
設計接收者:
RD(接收者)負責執行命令,需要對外暴露自己的能力,比如RD需要讓PM知道自己會寫bug,這樣PM有寫bug的需求才會給RD發出命令。又因爲有好多RD,所以需要抽象一下,每個具體的RD繼承該類。
public abstract class Receiver {
//抽象接收者,定義每個接收者都必須完成的業務
public abstract void doSomething();
}
設計客戶端:
PM(客戶端)是一個調用者,他負責發出一些無理的需求(命令,包括接收者和具體操作),然後告訴Leader(incoker),由Leader反饋給他最後的執行結果
public class Client {
public static void main(String[] args) {
//首先聲明調用者Invoker
Invoker invoker = new Invoker();
//定義接收者
Receiver receiver = new ConcreteReciver();
//定義一個發送給接收者的命令
Command command = new ConcreteCommand(receiver);
//把命令交給調用者去執行
invoker.setCommand(command);
invoker.action();
}
}
優缺點
通過上面的設計可以看出,優點就是:解決了命令發起者和實現者直接的高耦合的關係,新添加一個命令也很容易。缺點是: 可能會因爲命令的增多而導致命令類過多。