命令模式屬於對象的行爲模式。命令模式又稱爲行動(Action)模式或交易(Transaction)模式.
命令模式把一個請求或操做封裝到一個對象中。命令模式容許系統使用不一樣的請求把客戶端參數化,對請求排隊或記錄請求日誌,能夠提供命令的撤銷和恢復功能。
命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不一樣的對象。
每個命令都是一個操做:請求的一方發出請求要求執行一個操做,接收的一方收到請求,並執行操做。命令模式容許請求的一方和接收的一方獨立開來,使得請求的一方沒必要知道接收請求的一方的接口,更沒必要知道請求是怎麼被接收的,以及操做是否被執行,什麼時候被執行,以及是怎麼被執行的。
命令容許請求的一方和接收的一方可以獨立演化,從而具備如下優勢:
1.命令模式使新的命令很容易地被加入到系統裏
2.容許接收請求的一方決定是否要否決(Veto)請求
3.能較容易地設計一個命令隊列
4.能夠容易地實現對請求的Undo和Redo
5.在須要的狀況下,能夠較容易地將命令記入日誌
對熟悉C語言的讀者,命令模式即是面向對象形式的回呼(Callback).Java語言雖然不支持指針,可是命令模式能夠達到一樣的目的。
示例代碼以下:
1 //客戶角色
2 public class Client {
3 public static void main(String[] args) {
4 Receiver receive = new Receiver();
5 Command command = new ConcreteCommand(receive);
6 Invoker invoker = new Invoker(command);
7 invoker.action();
8 }
9 }
10 //請求者角色
11 class Invoker{
12 private Command command;
13
14 //構造方法
15 public Invoker(Command command){
16 this.command = command;
17 }
18 //行動方法
19 public void action(){
20 command.execute();
21 }
22 }
23 //接收者
24 class Receiver{
25 public Receiver(){
26
27 }
28 //行動方法
29 public void action(){
30 System.out.println("Action has been taken");
31 }
32 }
33
34 //抽象命令角色
35 interface Command{
36 //執行方法
37 void execute();
38 }
39 //具體命令角色
40 class ConcreteCommand implements Command{
41 private Receiver receiver;
42 //構造方法
43 public ConcreteCommand(Receiver receiver){
44 this.receiver = receiver;
45 }
46 @Override
47 public void execute() {
48 receiver.action();
49 }
50
51 }
命令模式涉及到5個角色:
1.客戶(Client)角色:建立了一個具體命令(ConcreteCommand)對象並肯定其接收者
2.命令(Command)角色:聲明瞭一個給全部具體命令類的抽象接口。這是一個抽象角色,一般由一個Java接口或抽象類實現
3.具體命令(ConcreteCommand)角色:定義一個接收者和行爲之間的弱耦合,實現 execute()方法,負責調用接收者的相應操做。execute()方法一般叫作執行方法。
4.請求者角色(Invoker):負責調用命令對象執行請求,相關的方法叫作行動方法
5.接收者角色(Receiver)角色:負責具體實施和執行一個請求。任何一個類均可以成爲接收者,實施和執行請求的方法叫作行動方法。
在什麼狀況下應當使用命令模式?
1.使用命令模式做爲回呼在面向對象系統中的替代,「回呼」講的即是先將一個函數登記上,而後在之後調用此函數
2.須要在不一樣的時間指定請求,將請求排隊。一個命令對象和原先的請求發出者能夠有不一樣的生命期。換言之,原先的請求發出者可能已經不在的,而命令對象自己仍然是活動的。這時命令的接收者能夠是本地的,也能夠是網絡的另一個地址。命令對象能夠在串形化以後傳送到另一臺機器上。
3.系統須要支持命令的撤消,命令對象能夠所狀態存儲起來,等到客戶端須要撤銷命令所產生的效果時,能夠調用undo()方法,把命令所產生的效果撤銷掉。命令對象還能夠提供redo()方法,以供客戶端在須要時,再從新實施命令的效果。
4.若是一個系統要將系統中全部的數據更新到日誌裏,以便在系統崩潰時,能夠根據日誌裏讀回全部的數據更新命令,從新調用execute()方法一條一條執行這些命令,從而恢復系統在崩潰前所作的數據更新。
5.一個系統須要支持交易(transcation).一個交易結構封裝了一組數據更新命令。使用命令模式來實現交易結構可使系統增長新的交易類型。
命令模式的優勢:
1.命令模式把請求一個操做的對象與知道怎麼執行這個操做的對象分割開
2.命令類與其餘任何別的類同樣,能夠修改和推廣
3.你能夠把命令對象聚合在一塊兒,合成爲合成命令。
4.因爲加進新 的具體命令類不影響其餘的類,所以增長新的具體命令類很容易。
命令模式的缺點:
1.使用命令模式會致使某些系統有過多的具體命令類。某些系統能夠須要十幾個,幾百個甚至幾千個具體命令類,這會使命令模式在這樣的系統裏變得不實際。