Docker 從入門到掉坑
阿新 • • 發佈:2020-11-30
Command Patterns
GoF定義:將請求作為一個物件來處理。使得可以使用不同的請求、佇列或者日誌請求來引數化客戶端。並且支援撤銷操作。
概念
通常,四個概念是相互關聯的
- command object:在接收端可以呼叫某個特定的方法,它儲存著可以呼叫receiver方法的引數
- invoker:只知道命令介面(接收符合Command介面宣告的物件),不知道具體哪個命令被呼叫
- client:持有invoker物件和command物件,客戶端決定哪些命令在一個特定的時間點執行,要實現這個功能,客戶端要將command物件傳給invoker物件
- receiver:命令的具體操作定義在這裡
例子
現實世界:我們不能改變過去發生的事情,但是我們希望原來可以那樣做,可惜沒有時光機的存在。但是日常生活中,我們可以不做或者重做很多事情,例如橡皮可以擦掉畫的畫,重新設計客廳。所以,取消和重做的操作是我們生活的一部分,我們通過一些內在或外在的命令來實現它們
程式碼世界:微軟的Paint軟體,我們通過工具欄可以隨時undo/redo很多操作
展示
程式碼
public class CommandPatternEx { public static void main(String[] args) { System.out.println("***Command Pattern Demo***\n"); Receiver intendedreceiver=new Receiver(); /*Client holds Invoker and Command Objects*/ Invoker inv = new Invoker(); MyUndoCommand unCmd = new MyUndoCommand(intendedreceiver); MyRedoCommand reCmd = new MyRedoCommand(intendedreceiver); inv.executeCommand(unCmd); inv.executeCommand(reCmd); } } interface ICommand { void doSomething(); } class MyUndoCommand implements ICommand { private Receiver receiver; public MyUndoCommand(Receiver receiver) { this.receiver = receiver; } @Override public void doSomething() { receiver.performUndoCommand(); } } class MyRedoCommand implements ICommand { private Receiver receiver; public MyRedoCommand(Receiver receiver) { this.receiver = receiver; } @Override public void doSomething() { receiver.performRedoCommand(); } } class Receiver { public void performUndoCommand() { System.out.println("Execution--Undo"); } public void performRedoCommand() { System.out.println("Execution--Redo"); } } class Invoker { ICommand cmd; public void executeCommand(ICommand cmd) { this.cmd = cmd; this.cmd.doSomething(); } }
Note
- 這個模式廣泛應用於undo/redo操作
- 回撥函式可以用這個模式設計(如果沒有函式式介面,可以傳入一個command物件,即在方法的不同狀態下執行不同的命令)
- 當我們處理事務時很有用,可以響應資料的變化(結合2,當資料庫資料在不同狀態下執行不同命令)
- 命令易於擴充套件。它們和其它的物件沒有什麼不同,在使用Command物件時,不需要改變現在系統的類結構(擴充套件介面即可)
- 另一種模式叫做(chain of responsibility)這個模式中,我們將一個請求傳給一系列的物件串(chain),希望這串物件中的任一個可以處理這個請求。但是在本例中,我們將請求傳給了特定的物件(invoker物件)
思考
這個模式核心在於將命令和具體操作解耦,即(Command物件+Receiver物件),而Invoker物件作為統一的調命令介面防止了新建各種command物件調不同的方法。所有的command物件都是客戶端組裝完成(要調的命令所需的引數,且包含一個Receiver類),然後直接傳入Invoker執行命令