[Head First設計模式]餐館中的設計模式——命令模式

系列文章

[Head First設計模式]山西面館中的設計模式——裝飾者模式html

[Head First設計模式]山西面館中的設計模式——觀察者模式設計模式

[Head First設計模式]山西面館中的設計模式——建造者模式ide

[Head First設計模式]餃子館(冬至)中的設計模式——工廠模式post

[Head First設計模式]一我的的平安夜——單例模式學習

[Head First設計模式]搶票中的設計模式——代理模式測試

[Head First設計模式]面向對象的3特徵5原則this

[Head First設計模式]鴨子模型——策略模式url

[Head First設計模式]雲南米線館中的設計模式——模版方法模式spa

實例

這裏採用書中餐廳訂餐的例子。餐廳訂餐的例子仍是比較簡單的,也比較好理解,書中的遙控器的例子,太長了,能把人繞暈,圖1:設計

圖2:

 

從餐廳到命令模式

命令模式類圖

Command:
        定義命令的接口,聲明執行的方法。
ConcreteCommand:
       具體的命令, 實現命令接口;一般會持有接收者,並調用接收者的功能來完成命令要執行的操做。
Receiver:
        接收者,真正執行命令的對象。任何類均可能成爲一個接收者,只要它可以實現命令要求實現的相應功能。
Invoker:
        要求命令對象執行請求,一般會持有命令對象,能夠持有不少的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操做的地方,也就是說至關於使用命令對象的入口。
Client:
        建立具體的命令對象,而且設置命令對象的接收者。注意這個不是咱們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱爲裝配者會更好理解,由於真正使用命令的客戶端是從Invoker來觸發執行。

這裏採用從實例到定義,倒着描述的方式,先從實例入手,有個大體印象,有助於理解。

命令模式定義

將「請求」封裝成對象,以便使用不一樣的請求、隊列或者日誌來參數化其它對象。命令模式也支持可撤銷的操做。

實例代碼實現

分析:帥哥顧客,土豪訂單,美女服務員,資深大廚的角色是什麼?

帥哥顧客:Client

土豪訂單:實現Command接口的具體Command

美女服務員:Invoker

資深大廚:Receiver

代碼實現:

Command接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wolfy.命令模式
{
    /// <summary>
    /// Command爲全部命令聲明一個接口,調用命令對象的excute方法
    /// 就可讓接收者進行相關的動做,
    /// </summary>
    public abstract class Command
    {
        public abstract void Execute();
    }
}

OrderCommand:具體的命令,繼承自Command抽象類

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading;
 6 using System.Threading.Tasks;
 7 
 8 namespace Wolfy.命令模式
 9 {
10     /// <summary>
11     /// 具體的命令
12     /// </summary>
13     public class OrderCommand : Command
14     {
15         /// <summary>
16         ///持有接受者對象
17         /// </summary>
18         SeniorChef receiver;
19         Order order;
20         public OrderCommand(SeniorChef receiver, Order order)
21         {
22             this.receiver = receiver;
23             this.order = order;
24         }
25         public override void Execute()
26         {
27         
28             Console.WriteLine("{0}桌的訂單:", order.DiningTable);
29             foreach (string item in order.FoodDic.Keys)
30             {
31                 //一般會轉調接收者對象的相應方法,讓接收者來真正執行功能
32                 receiver.MakeFood(order.FoodDic[item],item);
33             }
34             Thread.Sleep(2000);//停頓一下 模擬作飯的過程
35 
36             Console.WriteLine("{0}桌的飯弄好了", order.DiningTable);
37         }
38     }
39 }
View Code

Waitor:Invoker調用者,seniorChef:接收者 廚師類

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wolfy.命令模式
{
    /// <summary>
    /// 美女服務員類 這裏做爲調用者Invoker的角色
    /// </summary>
    public class Waitor
    {
        ArrayList commands = null;//能夠持有不少的命令對象
        public Waitor()
        {
            commands = new ArrayList();
        }
        public void SetCommand(Command cmd)
        {
            commands.Add(cmd);
        }
        /// <summary>
        /// 提交訂單 喊 訂單來了,廚師開始執行
        /// </summary>
        public void OrderUp()
        {
            Console.WriteLine("美女服務員:叮咚,大廚,新訂單來了.......");
            Console.WriteLine("資深廚師:收到");
            for (int i = 0; i < commands.Count; i++)
            {
                Command cmd = commands[i] as Command;
                if (cmd != null)
                {
                    cmd.Execute();
                }
            }
        }
    }
}
Waitor
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Wolfy.命令模式
 8 {
 9     /// <summary>
10     /// 資深大廚類 是命令的Receiver
11     /// </summary>
12     public class SeniorChef
13     {
14         public void MakeFood(int num,string foodName)
15         {
16             Console.WriteLine("{0}份{1}", num,foodName);
17         }
18     }
19 }
SeniorChef

訂單Order,封裝訂單內容,而後傳入OrderCommand,將訂單對象變爲命令對象

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Wolfy.命令模式
 8 {
 9     /// <summary>
10     /// 訂單
11     /// </summary>
12     public class Order
13     {
14         /// <summary>
15         /// 餐桌號碼
16         /// </summary>
17         public int DiningTable { set; get; }
18         /// <summary>
19         /// food  key:飯名 value:多少份
20         /// </summary>
21         public Dictionary<string, int> FoodDic { set; get; }
22     }
23 }
Order

測試端Program至關於Client角色

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Wolfy.命令模式
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             //program類 做爲客戶端
14             //建立2個order
15             Order order1 = new Order();
16             order1.DiningTable = 1;
17             order1.FoodDic = new Dictionary<string, int>() ;
18             order1.FoodDic.Add("西紅柿雞蛋麪",1);
19             order1.FoodDic.Add("小杯可樂",2);
20           
21             Order order2 = new Order();
22             order2.DiningTable = 3;
23             order2.FoodDic = new Dictionary<string, int>();
24             order2.FoodDic.Add("尖椒肉絲蓋飯", 1);
25             order2.FoodDic.Add("小杯雪碧", 1);
26             //建立接收者
27             SeniorChef receiver=new SeniorChef();
28             //將訂單這個兩個消息封裝成命令對象
29             OrderCommand cmd1 = new OrderCommand(receiver, order1);
30             OrderCommand cmd2 = new OrderCommand(receiver, order2);
31             //建立調用者 waitor
32             Waitor invoker = new Waitor();
33             //添加命令
34             invoker.SetCommand(cmd1);
35             invoker.SetCommand(cmd2);
36             //將訂單帶到櫃檯 並向廚師喊 訂單來了
37             invoker.OrderUp();
38             Console.Read();
39         }
40     }
41 }

測試結果:

總結

命令模式優勢:

1.下降對象之間的耦合度。
2.新的命令能夠很容易地加入到系統中。
3.能夠比較容易地設計一個組合命令。
4.調用同一方法實現不一樣的功能

缺點:

使用命令模式可能會致使某些系統有過多的具體命令類。由於針對每個命令都須要設計一個具體命令類,所以某些系統可能須要大量具體命令類,這將影響命令模式的使用。

適用環境:

1.系統須要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。
2.系統須要在不一樣的時間指定請求、將請求排隊和執行請求。
3.系統須要支持命令的撤銷(Undo)操做和恢復(Redo)操做。
4.系統須要將一組操做組合在一塊兒,即支持宏命令。

今天在家研究了一天命令模式,以上爲我的理解,若有不妥之處,請指出,一塊兒交流學習,謝謝。

參考:

Head first 設計模式

百度百科

相關文章
相關標籤/搜索