用心理解設計模式——命令模式 (Commond Pattern)
前置文章: 用心理解設計模式——設計模式的原則
設計模式相關程式碼已統一放至 我的 Github
一、定義
行為型模式之一。
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
(將請求封裝為物件,從而讓你用不同的請求、佇列、日誌請求,將客戶端引數化,並且支援撤銷操作)
二、結構解析
命令模式的一般結構有四種角色:抽象命令,具體命令,實現者,呼叫者。或者也可認為有五個角色,多一個客戶(裝配者)。
Command(抽象命令),負責定義一個命令執行的介面方法。
ConcreteCommand(具體命令),關聯/持有實現者,並在實現的命令執行介面方法中,利用實現者的提供的功能介面進行組織實現,形成具體命令。
Implementor(實現者),命令的實際執行者。只做自己的事,暴露出自己能提供的功能介面,不關心命令。
Invoker (呼叫者),使用命令物件的入口,讓命令開始執行,可能組合/持有了N條命令。只關心發出怎樣的命令。
三、評價
命令模式,作為行為型模式之一,它將 “命令” 這個抽象概念抽象為類,並定義了請求者(呼叫者)和實現者以“命令”進行通訊的行為過程,使請求者和實現者之間的直接耦合得以解除。
簡單了當的說,命令模式解決了呼叫者在產生新命令時,實現者都得去迎合呼叫者提供相應介面的問題。它讓具體命令的擴充套件,不再需要修改實現者,而是在命令類的的Execute方法中,對實現者提供的功能方法換一種組織方式。(除非實現者提供的功能方法不足以組織實現新的命令)
Implementor(實現者),很多地方都稱其為 Receiver(接收者)。NRatel認為,這很容易讓人產生誤解
四、實現
namespace Commond
{
//命令實現者,做自己的事,不關心命令
public class Implementor
{
public void DoSthX() { }
public void DoSthY() { }
public void DoSthZ() { }
}
//抽象命令
public abstract class Command
{
public abstract void Execute();
}
//具體命令A
public class ConcreteCommandA : Command
{
//持有實現者
private Implementor implementor;
public ConcreteCommandA(Implementor implementor)
{
this.implementor = implementor;
}
public override void Execute()
{
//組織接收者的功能,實現具體命令
//例如這裡要使用接收者的XY功能方法
this.implementor.DoSthX();
this.implementor.DoSthY();
}
}
//具體命令B
public class ConcreteCommandB : Command
{
private Implementor implementor;
public ConcreteCommandB(Implementor implementor)
{
this.implementor = implementor;
}
public override void Execute()
{
//組織接收者的功能,實現具體命令
//例如這裡要使用接收者的Z功能方法
this.implementor.DoSthZ();
}
}
//命令呼叫者
public class Invoker
{
//組合持有命令,這裡簡化為引數方式傳入
public void Invoke(Command command)
{
command.Execute();
}
}
//客戶,命令裝配
public class Client
{
public Client()
{
//構造命令實現者
Implementor implementor = new Implementor();
//裝配具體命令, 將命令接受者與具體命令關聯
ConcreteCommandA concreteCommandA = new ConcreteCommandA(implementor);
ConcreteCommandB concreteCommandB = new ConcreteCommandB(implementor);
//構造命令呼叫者
Invoker invoker = new Invoker();
//命令作為引數,提供給命令呼叫者
invoker.Invoke(concreteCommandA);
invoker.Invoke(concreteCommandB);
}
}
}
五、撤銷操作
TODO