命令模式(Command Pattern)。
命令模式是一個高內聚的模式,其定義為:
將一個請求封裝成一個物件,從而讓你使用不同的請求把客戶端引數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。
通用程式碼:
- Receiver接收者角色
該角色就是幹活的角色,命令傳遞到這裡是應該被執行的。
- Command命令角色
需要執行的所有命令都在這裡宣告。
- Invoker呼叫者角色
接收到命令,並執行命令。
通用Receiver類
public abstract class Receiver {
// 抽象接收者,定義每個接收者都必須完成的業務
public abstract void doSomething();
}
很奇怪,為什麼Receiver是一個抽象類?那是因為接收者可以有多個,有多個就需要定義一個所有特性的抽象集合——抽象的接收者。
具體的Receiver類
pubic class ConcreteReciver1 extends Receiver {
// 每個接收者都必須處理一定的業務邏輯
public void doSomething(){}
}
pubic class ConcreteReciver2 extends Receiver {
// 每個接收者都必須處理一定的業務邏輯
public void doSomething(){}
}
接收者可以是N個,這要依賴業務的具體定義。命令角色是命令模式的核心。
抽象的Command類
public abstract class Command {
// 定義一個子類的全域性共享變數;
protected final Receiver receiver;
// 實現類必須定義一個接收者
public Command(Receiver _receiver) {
this.receiver = _receiver;
}
// 每個命令類都必須有一個執行命令的方法
public abstract void execute();
}
根據環境的需求,具體的命令類也可以有N個。
具體的Command類
public class ConcreteCommand1 extends Command {
// 宣告自己的的預設接收者
public ConcreteCommand1(){
super(new ConcreteReciver1());
}
// 設定新的接收者
public ConcreteCommand1(Receiver _receiver) {
super(_receiver);
}
// 必須實現一個命令
public void execute(){
// 業務處理
super.receiver.doSomething();
}
}
public class ConcreteCommand2extends Command {
// 宣告自己的的預設接收者
public ConcreteCommand2(){
super(new ConcreteReciver2());
}
// 設定新的接收者
public ConcreteCommand2Receiver _receiver) {
super(_receiver);
}
// 必須實現一個命令
public void execute(){
// 業務處理
super.receiver.doSomething();
}
}
呼叫者Invoker類
public class Invoker {
private Command command;
// 受氣包,接受命令
public void setCommand(Command _command) {
this.command = _command;
}
// 執行命令
public void action() {
this.command.execute();
}
}
場景類
public class Client {
public static void main(String[] args) {
// 首先宣告呼叫者Invoker
Invoker invoker = new Invoker();
// 定義一個傳送給接收者的命令
Command command = new ConcreteCommand1();
// 把命令交給呼叫者去執行
invoker.setCommand(command);
invoker.action();
}
}
優點:
- 類間解耦
呼叫者角色與接收者角色之間沒有任何依賴關係,呼叫者實現功能時只需呼叫Command抽象類的execute方法就可以,不需要了解到底是哪個接收者執行。
- 可擴充套件性
Command的子類可以非常容易的擴充套件,而呼叫者Invoker和高層次的模組Client不產生嚴重的程式碼耦合。
- 命令模式結合其他模式會更優秀
命令模式可以結合責任鏈模式,實現命令族解析任務,結合模板方法模式,則可以減少Command子類的膨脹問題。
缺點:
命令模式也是有缺點的,請看Command的子類:如果有N個命令,問題就出來了,Command的子類就可不是幾個,而是N個,這個類膨脹的非常大,這個就需要讀者在專案中慎重考慮使用。
使用場景:
只要你認為是命令的地方就可以採用命令模式。例如,在GUI開發中,一個按鈕的點選是一個命令,可以採用命令模式;模擬DOS命令的時候,當然也要採用命令模式;觸發——反饋機制等。
擴充套件:
- 反悔問題
有兩種方法解決:一是結合備忘錄模式還原最後狀態,該方法適合接收者為狀態的變更情況,而不適合事件處理;二是通過增加一個新的命令,實現事件的回滾。
示例程式碼:
抽象組
public abstract class Group {
// 甲乙雙方分開辦公,如果你要和某個組討論,你首先要找到這個組
public abstract void find();
// 被要求增加功能
public abstract void add();
// 被要求刪除功能
public abstract void delete();
// 被要求修改功能
public abstract void change();
// 被要求給出所有的變更計劃
public abstract void plan();
// 每個接收者都要對直接執行的任務可以回滾
public void rollBack() {
// 根據日誌進行回滾
}
}
需求組
public class RequirementGroup extends Group {
// 客戶要求需求組過去和他們談
public void finid(){
System.out.println("找到需求組...");
}
// 客戶要求增加一項需求
public void add() {
System.out.println("客戶要求增加一項需求...");
}
// 客戶要求修改一項需求
public void change() {
System.out.println("客戶要求修改一項需求...");
}
// 客戶要求刪除一項需求
public void delete() {
System.out.println("客戶要求刪除一項需求...");
}
// 客戶要求給出變更計劃
public void plan() {
System.out.println("客戶要求需求變更計劃");
}
}
美工組(PageGroup)、程式碼組(CodeGroup)程式碼與需求組(RequirementGroup)類似,故省略。
抽象命令類
public abstract class Command {
// 把三個組都定義好,子類可以直接使用
protected RequirementGroup rq = new RequirementGroup(); // 需求組
protected PageGroup pg = new PageGroup(); // 美工組
protected CodeGroup cg = new CodeGroup(); // 程式碼組
// 只有一個方法,你要我做什麼事情
public abstract void execute();
}
增加需求的命令
public class AddRequirementCommand extends Command {
// 執行增加一項需求的命令
public void execute() {
// 找到需求組
super.rg.find();
// 增加一份需求
super.rg.add();
// 頁面也要增加
super.pg.add();
// 功能也要增加
super.cg.add();
// 給出計劃
super.rg.plan();
}
}
撤銷命令
public class CancelDeletePageCommand extends Command {
// 撤銷刪除一個頁面的命令
public void execute() {
super.pg.rollBack();
}
}
負責人
public class Invoker {
// 什麼命令
private Command command;
// 客戶發出命令
public void setCommand(Command command) {
this.command = command;
}
// 執行客戶的命令
public void action() {
this.command.execute();
}
}
增加一項需求
public class Client {
public static void main(String[] args) {
// 定義我們的接頭人
Invoker xiaoSan = new Invoker(); // 接頭人就是小三
// 客戶要求增加一項需求
System.out.println("------------------------客戶要求增加一項需求---------------");
// 客戶給我們下命令來
Command command =new AddRequirementCommand();
// 接頭人接收命令
xiaoSan.setCommand(command);
// 接頭人執行命令
xiaoSan.action();
}
}
public class ConcreteCommand1 extends Command {
// 對哪個Receiver類進行命令處理
private Receiver receiver;
// 建構函式傳遞接收者
public ConcreteCommand1(Receiver _receiver) {
this.receiver = _receiver;
}
// 必須實現一個命令
public void execute(){
// 業務處理
this.receiver.doSomething();
}
}
}
相關文章
- C++設計模式——命令模式(command pattern)C++設計模式
- JAVA設計模式之 命令模式【Command Pattern】Java設計模式
- 設計模式:命令模式(Command Pattern)及例項設計模式
- 【圖解設計模式系列】The Command Pattern: 命令列模式圖解設計模式命令列
- 4/24 設計模式之命令設計模式 Command Pattern設計模式
- 使用C# (.NET Core) 實現命令設計模式 (Command Pattern)C#設計模式
- 設計模式-命令模式(Command)設計模式
- 設計模式——18命令模式(Command)設計模式
- Java設計模式(22)命令模式(Command模式)Java設計模式
- [review]Design Pattern:CommandView
- 命令模式 :Command(轉自LoveCherry)模式
- fastadmin命令列模式--commandAST命令列模式
- 設計模式--命令模式Command(行為型)設計模式
- C#設計模式系列:命令模式(Command)C#設計模式
- 設計模式的征途—19.命令(Command)模式設計模式
- 命令模式與go-redis command設計模式GoRedis
- 設計模式之策略模式和狀態模式(strategy pattern & state pattern)設計模式
- command模式模式
- 策略模式【Strategy Pattern】模式
- 代理模式(Proxy Pattern)模式
- 設計模式-策略模式(strategy pattern)設計模式
- 建造者模式(Builder Pattern)模式UI
- 規格模式(Specification Pattern)模式
- 裝飾模式 (Decorator Pattern)模式
- 原型模式(Prototype Pattern)。原型模式
- 中介者模式(Mediator Pattern)。模式
- 狀態模式(State pattern)模式
- 設計模式--裝飾模式(Decorator Pattern)設計模式
- 設計模式之代理模式(proxy pattern)設計模式
- 設計模式-裝飾模式(Decorator Pattern)設計模式
- 設計模式--建造者模式(Builder Pattern)設計模式UI
- 設計模式--原型模式(Prototype Pattern)設計模式原型
- 設計模式-狀態模式(State Pattern)設計模式
- 【大道模式】享元模式-FlyWeight Pattern模式
- redis的command命令Redis
- Command 模式 Step by Step模式
- composite pattern(組合模式)模式
- 單例模式(Singleton Pattern)單例模式