1. 程式人生 > >深入淺出設計模式——命令模式(Command Pattern)

深入淺出設計模式——命令模式(Command Pattern)

轉載自:https://www.cnblogs.com/Bobby0322/p/4195240.html

模式動機

在軟體設計中,我們經常需要向某些物件傳送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程式執行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計,使得請求傳送者與請求接收者消除彼此之間的耦合,讓物件之間的呼叫關係更加靈活。
命令模式可以對傳送者和接收者完全解耦,傳送者與接收者之間沒有直接引用關係,傳送請求的物件只需要知道如何傳送請求,而不必知道如何完成請求。這就是命令模式的模式動機。

模式定義
命令模式(Command Pattern):將一個請求封裝為一個物件,從而使我們可用不同的請求對客戶進行引數化;對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。命令模式是一種物件行為型模式,其別名為動作(Action)模式或事務(Transaction)模式。
Command Pattern: Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. 
Frequency of use: medium high
UML圖


模式結構
命令模式包含如下角色:
Command: 抽象命令類
ConcreteCommand: 具體命令類
Invoker: 呼叫者
Receiver: 接收者
Client:客戶類

模式分析
命令模式的本質是對命令進行封裝,將發出命令的責任和執行命令的責任分割開。
每一個命令都是一個操作:請求的一方發出請求,要求執行一個操作;接收的一方收到請求,並執行操作。
命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的介面,更不必知道請求是怎麼被接收,以及操作是否被執行、何時被執行,以及是怎麼被執行的。

命令模式使請求本身成為一個物件,這個物件和其他物件一樣可以被儲存和傳遞。 
命令模式的關鍵在於引入了抽象命令介面,且傳送者針對抽象命令介面程式設計,只有實現了抽象命令介面的具體命令才能與接收者相關聯。

模式例項與解析
烤羊肉串引來的思考—命令模式
體系結構

Command: 抽象命令類 Command.cs

複製程式碼
namespace CommandPattern
{
    //抽象命令類
    public abstract class Command
    {
        protected Barbecuer receiver;
        public Command(Barbecuer receiver)
        {
            this.receiver = receiver;
        }
        //執行命令
        abstract
public void ExecuteCommand(); } }
複製程式碼

ConcreteCommand: 具體命令類 BakeMuttonCommand.cs

複製程式碼
namespace CommandPattern
{
    //烤羊肉串命令
    class BakeMuttonCommand : Command
    {
        public BakeMuttonCommand(Barbecuer receiver)
            : base(receiver)
        {
        }
        public override void ExecuteCommand()
        {
            receiver.BakeMutton();
        }
    }
}
複製程式碼

BakeChickenWingCommand.cs

複製程式碼
namespace CommandPattern
{
    //烤雞翅命令
    class BakeChickenWingCommand : Command
    {
        public BakeChickenWingCommand(Barbecuer receiver)
            : base(receiver)
        {
        }
        public override void ExecuteCommand()
        {
            receiver.BakeChickenWing();
        }
    }
}
複製程式碼

Invoker: 呼叫者 Waiter.cs

複製程式碼
using System;
using System.Collections.Generic;

namespace CommandPattern
{
    //服務員
    public class Waiter
    {
        //增加存放具體命令的容器
        private IList<Command> orders = new List<Command>();

        //設定訂單
        public void SetOrder(Command command)
        {
            if (command.ToString() == "CommandPattern.BakeChickenWingCommand")
            {
                Console.WriteLine("服務員:雞翅沒有了,請點別的燒烤.");
            }
            else
            {
                orders.Add(command);
                Console.WriteLine("增加訂單:" + command.ToString() + " 時間:" + DateTime.Now.ToString());
            }
        }
        //取消訂單
        public void CancelOrder(Command command)
        {
            orders.Remove(command);
            Console.WriteLine("取消訂單:" + command.ToString() + " 時間:" + DateTime.Now.ToString());
        }
        //通知全部執行
        public void Notify()
        {
            foreach (Command cmd in orders)
            {
                cmd.ExecuteCommand();            }
        }
    }
}
複製程式碼

Receiver: 接收者 Barbecuer.cs

複製程式碼
using System;

namespace CommandPattern
{
    //烤肉串者
    public class Barbecuer
    {
        //烤羊串
        public void BakeMutton()
        {
            Console.WriteLine("烤羊肉串!");
        }
        public void BakeChickenWing()
        {
            Console.WriteLine("烤雞翅!");
        }
    }
}
複製程式碼

Client:客戶類

複製程式碼
using System;

namespace CommandPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            //開店前的準備
            Barbecuer boy = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChikenWingCommand1 = new BakeChickenWingCommand(boy);
            Waiter girl = new Waiter();
            //開門營業 顧客點菜
            girl.SetOrder(bakeMuttonCommand1);
            girl.SetOrder(bakeMuttonCommand2);
            girl.SetOrder(bakeChikenWingCommand1);
            //點菜完畢,通知廚房
            girl.Notify();

            Console.Read();
        }
    }
}
複製程式碼

模式優缺點
命令模式的優點
 降低系統的耦合度。
 新的命令可以很容易地加入到系統中。
 可以比較容易地設計一個命令佇列和巨集命令(組合命令)。
 可以方便地實現對請求的Undo和Redo。

命令模式的缺點
 使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。

模式適用環境
在以下情況下可以使用命令模式:
 系統需要將請求呼叫者和請求接收者解耦,使得呼叫者和接收者不直接互動。
 系統需要在不同的時間指定請求、將請求排隊和執行請求。
 系統需要支援命令的撤銷(Undo)操作和恢復(Redo)操作。
 系統需要將一組操作組合在一起,即支援巨集命令。

【宣告與感謝】
本文,站在許多巨人的肩膀上,借鑑和引用了許多他人擁有版權的作品或著述,在此,對前人們的貢獻致謝。並同時公佈引用的內容、原作者或來源(一些來源於網際網路的內容本人無法追述本源,深表遺憾)。

【參考文獻】
《設計模式—可複用面向物件軟體的基礎》作者: [美] Erich Gamma / Richard Helm / Ralph Johnson / John Vlissides 譯者: 李英軍 / 馬曉星 / 蔡敏 / 劉建中 等 機械工業出版社
《重構—改善既有程式碼的設計》作者: Martin Fowler譯者:候捷 中國電力出版社
《敏捷軟體開發—原則、模式與實踐》作者: Robert C. Martin 清華大學出版社
《程式設計師修煉之道—從小工到專家》作者: Andrew Hunt / David Thomas 電子工業出版社
《Head First 設計模式》作者: 弗里曼 譯者: O'Reilly Taiwan公司 中國電力出版社
《設計模式之禪》 作者: 秦小波 機械工業出版社
MSDN WebCast 《C#面向物件設計模式縱橫談》 講師:李建忠
劉偉. 設計模式. 北京:清華大學出版社, 2011.
劉偉. 設計模式實訓教程. 北京:清華大學出版社, 2012.
《大話設計模式》 作者: 程傑 清華大學出版社
《C#圖解教程》作者: 索利斯 譯者: 蘇林 / 朱曄 人民郵電出版社
《你必須知道的.NET》作者: 王濤
《專案中的.NET》作者: 李天平 電子工業出版社
《Microsoft .NET企業級應用架構設計》作者: (美)埃斯波西託等編著 譯者: 陳黎夫
http://www.dofactory.com/Patterns/Patterns.aspx .NET Design Patterns
http://www.cnblogs.com/zhenyulu 部落格作者:呂震宇
http://www.cnblogs.com/terrylee 部落格作者:李會軍
http://www.cnblogs.com/anlyren/ 部落格作者:anlyren
http://www.cnblogs.com/idior 部落格作者:idior
http://www.cnblogs.com/allenlooplee 部落格作者:Allen lee
http://blog.csdn.net/ai92 部落格作者:ai92
http://www.cnblogs.com/umlonline/ 部落格作者:張傳波
http://www.cnblogs.com/lovecherry/ 部落格作者:LoveCherry

相關推薦

深入淺出設計模式——命令模式Command Pattern

轉載自:https://www.cnblogs.com/Bobby0322/p/4195240.html 模式動機 在軟體設計中,我們經常需要向某些物件傳送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程式執行時指定具體的請求接收者即可,此

c#設計模式系列:命令模式Command Pattern

為我 pattern 代碼 spa pro round 產生 技術分享 image 引言 命令模式,我感覺“命令”就是任務,執行了命令就完成了一個任務。或者說,命令是任務,我們再從這個名字上並不知道命令的發出者和接受者分別是誰,為什麽呢?因為我們並不關心他們是誰,發出命令

C#設計模式(15)——命令模式Command Pattern

兩個 學院 做的 text server trac handle 接受 color 一、前言   之前一直在忙於工作上的事情,關於設計模式系列一直沒更新,最近項目中發現,對於設計模式的了解是必不可少的,當然對於設計模式的應用那更是重要,可以說是否懂得應用設計模式在項目中是衡

重走Java設計模式——命令模式Command Pattern

命令模式 定義 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫物件尋找可以處理該命令的合適的物件,並把該命令傳給相應的物件,該物件執行命令。 命令模式設計角色

設計模式命令模式Command Pattern

摘要 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫 介紹 意圖:將一個請求封裝成一個物件,從而使您可以用不同的請求對客戶進行引數化。 主要解決:在軟體系統中,行為請求者與行為實現者通常是一種緊

設計模式命令模式Command Pattern

/** * 命令模式。 * @author Bright Lee */ public class CommandPattern { public static void main(String[] args) { Receiver receiver = new Receiver

Unity遊戲設計模式命令模式Command Pattern

        我想大部分的新人跟我一樣剛開始學習Unity的時候,控制人物行的寫法是這樣的。 using UnityEngine; using System.Collections; public class Test : MonoBehaviour { <

設計模式 —— 命令模式Command Pattern

命令模式(Command Pattern) 概念: 概述:在軟體設計中,我們經常會遇到某些物件傳送請求,然後某些物件接受請求後執行,但傳送請求的物件可能並不知道接受請求的物件是誰,執行的是什麼動作。此時可通過 命令模式 來實現,讓傳送者和接受者完全

設計模式——命令模式Command Pattern

一、命令模式的定義 將“請求”封裝成物件,以便使用不同的請求,佇列或者日誌來引數化其他物件。命令模式也支援可撤銷。 命令介面–ICommand public interface ICommand { public void execut

設計模式命令模式Command Pattern

命令模式 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫物件尋找可以處理該命令的合適的物件,並把該命令傳給相應的物件,該物件執行命令。 介紹 意圖:將一個請求封裝成一個物件,

命令模式Command pattern-- 請求與實現的解耦

[align=center][size=x-large]PART 1 請求與實現[/size][/align] [b]什麼叫請求:[/b]使用者選中一行文字,點選複製按鈕,意圖將文字複製到剪貼簿,這個意圖就叫做請求,但具體到程式中,這個請求被具象化為一個複製按鈕

9.命令模式Command Pattern

1.定義 將一個請求封裝成一個物件,從而讓你使用不同的請求把客戶端引數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。 命令模式屬於行為模式。 2.命令模式的使用場景 只要我們認為是命令的地方就可以採用命令模式,比如在GUI開發中,一個按鈕的點選是一個命令;觸

設計模式-命令模式Command

命令模式:將一個請求封裝為一個物件,從而可用不同的請求對客戶進行引數化;對請求排隊或記錄日誌,以及支援可撤銷的操作,將”發出請求的物件”和”接收與執行這些請求的物件”分隔開來。   角色和職責: 1.Command:    宣告執行操作的介面 2.Concrete Co

設計模式(行為型模式) ----- 命令模式Command

命令模式很好理解,舉個例子,司令員下令讓士兵去幹件事情,從整個事情的角度來考慮,司令員的作用是,發出口令,口令經過傳遞,傳到了士兵耳朵裡,士兵去執行。這個過程好在,三者相互解耦,任何一方都不用去依賴其他人,只需要做好自己的事兒就行,司令員要的是結果,不會去關注到

java設計模式——命令模式(Command Pattern)

概述:        在軟體開發中,我們經常需要向某些物件傳送請求(呼叫其中的某個或某些方法),但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,此時,我們特別希望能夠以一種鬆耦合的方式來設計軟體,使得請求傳送者與請求接收者能夠消除彼此之間的耦合,讓物件之間的呼叫關

設計模式之委派模式Delegate Pattern深入淺出

學習目標:精簡程式邏輯,提升程式碼的可讀性。 內容定位:希望通過對委派模式的學習,讓自己寫出更加優雅的程式碼的人群。 委派模式定義: 委派模式(Delegate Pattern)的基本作用是負責任務的排程和分配任務,跟代理模式很像,可以看作是一種特殊情況下的靜態代理的全權代理,但是代理模式注重過程,而委派模

設計模式之 - 模板模式Template Pattern

process egg lec pass jdbcutils ima tint new sta 引入:這幾天在看一本講spring源碼的書《SPRING技術內幕》裏面在講加載配置文件的時候,可以有不同的加載方式,如根據文件系統目錄加載配置文件(FileSystemXmlAp

設計模式——命令模式C++實現

clear cto ive pre urn bak std oot style 1 [root@ ~/learn_code/design_pattern/19_order]$ cat order.cpp 2 #include <

設計模式之 - 代理模式Proxy Pattern

ride proxy idt object catch 實例化 圖片 null 人在 代理模式:代理是一種常用的設計模式,其目的就是為其他對象提供一個代理以控制對某個對象的訪問。代理類負責為委托類預處理消息,過濾消息並轉發消息,以及進行消息被委托類執行後的後續處理。很多可以

【JAVA設計模式】外觀模式Facade Pattern

簡單 產生 creat ide oid dsm ref 功能 .net 一 定義 為子系統中的一組接口提供一個一致的界面。Facade模式定義了一個高層的接口,這個接口使得這一子系統更加easy使用。 二 案例 一個子系統中擁有3個模塊。每一個模塊