1. 程式人生 > >用心理解設計模式——命令模式 (Commond Pattern)

用心理解設計模式——命令模式 (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認為,這很容易讓人產生誤解

。因為“接收者”這個詞讓人感覺他是拿到命令進行處理的,實際上,它只是提供自己應提供的功能方法,並不關心命令(非常滿足單一職責和迪米特法則)。是具體命令類,在它實現的Execute方法中,利用實現者提供的功能方法組織和處理了具體的命令。

四、實現

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