介紹:
命令模式是一種行為型模式。將一個請求封裝成一個對象,從而讓用戶使用不同的請求把客戶端參數(shù)化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。
備注:所謂的參數(shù)化,使用端使用執(zhí)行同一個請求,但是為請求配置不同的命令對象,那就會執(zhí)行不同的功能。例如:使用者按下一個按鈕,到底是開機還是重啟,那要看參數(shù)化配置的是哪一個具體的按鈕對象。
類圖:

Receiver(接受者角色):負責具體實施一個請求,執(zhí)行具體邏輯的角色。
Command(命令角色):定義好命令的接口,用來約束所有的命令對象。
ConcreteCommand(具體命令角色):實現(xiàn)Command接口,在execute方法中調用接受者角色的相關方法。
Invoker(請求者角色):調用命令對象執(zhí)行具體請求。
用法:
? 需要對行為進行記錄、撤銷或重做、事務等處理時
? 抽象出待執(zhí)行的動作以參數(shù)化某對象。類似過程設計中的回調機制,而命令模式是回調機制的一個面向對象的替代品
個人理解:
? 命令模式核心就是將各種請求封裝成一個命令對象。命令對象作為一個“中間人”解耦行為請求者與行為執(zhí)行者。
? 用法中提到的進行記錄、撤銷或重做、事務等處理,描述的是一些稍微復雜點的業(yè)務,行為請求者實現(xiàn)一個功能時可能并不是立即執(zhí)行,甚至還需要做一些邏輯管理,這時候就需要考慮使用命令模式了。
例子:
例子1 我們使用電腦的時候,開機、關機、重啟都是作為系統(tǒng)的一條命令,用這個例子簡單介紹命令模式的結構。
例子2 命令模式的用法中提到是回調機制的一個替代品,
1、簡單使用命令模式
1.1、定義命令接口Command接口
public interface Command {
void execute(); //執(zhí)行命令
}
約束好所有命令子類,必須實現(xiàn)execute()方法。
1.2、實現(xiàn)接受者角色Receiver,負責具體邏輯的實現(xiàn)
分別是關機、重啟、取消三個操作的具體實現(xiàn),這里我們簡單輸出一下:
public class Receiver {
public void shutdown(){
System.out.println("執(zhí)行關機操作");
System.out.print("開始關機....");
}
public void restart(){
System.out.println("執(zhí)行重啟操作");
System.out.print("開始關機....");
System.out.print("開始開機....");
}
public void cancel(){
System.out.print("取消操作");
}
}
1.3、實現(xiàn)命令子類ConcreteCommand
命令子類作為“中間人”,負責執(zhí)行Recevier相關方法。
public class RestartCommand implements Command {
private Receiver receiver;
public RestartCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
System.out.println("命令角色執(zhí)行重啟命令");
receiver.restart();
}
}
省略ShutdownCommand類與CancelCommand類,結構雷同。
1.4、創(chuàng)建Invoker,負責調用命令對象執(zhí)行請求
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void action() {
System.out.println("調用者執(zhí)行命令");
command.execute();
}
}
Invoker作為命令的調用者,讓適合的命令對象執(zhí)行命令。
1.5、測試與實現(xiàn)
public class Test {
public static void main(String[] args) {
//構造一個接受者對象
Receiver receiver = new Receiver();
//根據(jù)接受者對象創(chuàng)建一條命令
Command command = new RestartCommand(receiver);
//根據(jù)具體命令對象構造請求者
Invoker invoker = new Invoker(command);
//執(zhí)行命令
invoker.action();
}
}
調用者執(zhí)行命令
命令角色執(zhí)行重啟命令
執(zhí)行重啟操作
開始關機....
開始開機....
關機重啟的例子簡單實現(xiàn)就完成了。讀到這里只是能體會到這個模式能解耦和具體結構,實際開發(fā)中用處不怎么大。例如,我們關機的時候通常會遇到以下情況:某個應用程序還卡住了,關不了機,重啟不了,這種情況怎么處理呢?
1.6、改進一下Invoker
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void action(boolean process) {
if (process){
System.out.print("進程還沒退出,終止命令!");
return;
}
System.out.println("調用者執(zhí)行命令");
command.execute();
}
}
在action()方法加多個邏輯,判斷后臺進程是否全部退出。我們發(fā)現(xiàn),Invoker請求者負責接受命令對象,并作出邏輯判斷,最后調用命令對象,甚至直接理解成它是一個命令管理者CommandController。
2、代替回調機制
我另外一篇文章詳細分析過回調機制,觀察者模式——監(jiān)聽與回調,大家可以去看看。
下面簡單寫一下回調機制:
2.1、回調類
public interface ICallBack {
void callback();
}
2.2、需要執(zhí)行回調的類
public class A {
private ICallBack callBack;
public void setCallBack(ICallBack callBack){
this.callBack = callBack;
}
public void doSomething(){
System.out.print("do something!");
if (callBack != null){
callBack.callback();
}
}
}
2.3、實現(xiàn)
public class Client {
public static void main(String[] args) {
A a = new A();
a.setCallBack(new ICallBack() {
@Override
public void callback() {
System.out.print("執(zhí)行回調");
}
});
a.doSomething();
}
}
2.4、命令模式代替回調機制
public class ConcreteCommand implements ICallBack{
@Override
public void callback() {
System.out.print("執(zhí)行回調");
}
}
public class Client {
public static void main(String[] args) {
A a = new A();
a.setCallBack(new ConcreteCommand());//改了這里
a.doSomething();
}
}
回調機制:回調(Callback)函數(shù)是指函數(shù)先在某處注冊,而它將在稍后某個需要的時候被調用,它實際上是一種參數(shù)化機制。
命令模式:命令模式的設計意圖就是“將一個請求封裝為一個對象,從而使用戶可用不同的請求對客戶進行參數(shù)化”。
看下代碼,用具體命令對象類代替了匿名類回調函數(shù),同樣都是參數(shù)化的配置機制,就稱為代替了。本質上,以上其實是兩種回調的寫法。
總結:
? 命令模式理解上比較簡單,但使用上相對來說比較繁瑣,一個簡單的調用關系被解耦成多個部分。
? 用命令模式的參數(shù)化概念再回顧一下回調
? 在備忘錄模式中同樣提到撤銷與重做這個業(yè)務。如果在某個系統(tǒng)使用命令模式時,需要實現(xiàn)命令的撤銷功能,那么命令模式可以使用備忘錄模式來存儲可撤銷操作的狀態(tài)。
感謝您的閱讀~
推薦閱讀
基礎篇:
設計模式前篇之——UML類圖必會知識點
設計模式前篇之——一起過一下面向對象的概念
創(chuàng)建型模式:
簡易理解設計模式之:簡單工廠模式——來試試接入支付功能
簡易理解設計模式之:工廠方法模式——數(shù)據(jù)存儲例子
簡易理解設計模式之:抽象工廠模式——更換數(shù)據(jù)庫例子
簡易理解設計模式之:建造者模式——學習使用“鏈式調用”
簡易理解設計模式之:原型模式——深、淺拷貝的概念
簡易理解設計模式之:單例模式——單例模式的幾種常用寫法
結構型模式:
簡易理解設計模式之:適配器模式——Android列表視圖控件設計方式
簡易理解設計模式之:橋接模式——穿衣服經典案例2
簡易理解設計模式之:組合模式——實現(xiàn)View中的樹狀結構
簡易理解設計模式之:裝飾模式——穿衣服經典案例
簡易理解設計模式之:外觀模式——第三方SDK的幫助類
簡易理解設計模式之:享元模式——五子棋游戲例子
簡易理解設計模式之:代理模式——iOS視圖控件設計方式
行為型模式:
簡易理解設計模式之:策略模式——優(yōu)化一下支付功能
簡易理解設計模式之:模板方法模式——Android中的BaseActivity基類
簡易理解設計模式之:觀察者模式——監(jiān)聽與回調
簡易理解設計模式之:狀態(tài)模式——優(yōu)化登錄操作
簡易理解設計模式之:備忘錄模式——Word文檔的工作原理
簡易理解設計模式之:迭代器模式——遍歷對象的好幫手
簡易理解設計模式之:命令模式——實現(xiàn)命令的參數(shù)化配置
簡易理解設計模式之:責任鏈模式——OA中請假流程示例
簡易理解設計模式之:中介者模式——多人聊天室例子
簡易理解設計模式之:解釋器模式——語言和文法
簡易理解設計模式之:訪問者模式——員工考核例子