《Head First設計模式》第六章筆記-命令模式

封裝調用-命令模式

?

命令模式可將“動作的請求者”從“動作的執行者”對象中解耦。

本篇中將不再描述書中所引入的“巴斯特家電自動化公司”的遙控器控制案例,而使用簡單易懂的餐廳案例。

在開始之前,讓我們通過一個現實中的例子來了解命令模式。

理解命令模式

讓我們回到餐廳,研究顧客、女招待、訂單,以及快餐廚師之間的交互。通過這樣的互動,你將體會到命令模式所涉及的對象,也會知道它們之間如何被解耦。

將以上流程代入到編程的對象中進一步思考對象與方法之間的關系:

分析餐廳對應的角色與職責

1、顧客:發出請求的對象。
2、訂單:封裝了準備餐點的請求。
3、女招待:接收訂單,然后調用訂單的orderUp方法,將訂單提交到柜臺,無需知道訂單細節。
4、廚師:收到訂單后,按訂單實現對應餐點的所有方法制作餐點。

從餐廳到命令模式

命令模式類圖

  • Command:定義命令的接口,聲明執行的方法。
  • ConcreteCommand: 具體的命令, 實現命令接口;通常會持有接收者,并調用接收者的功能來完成命令要執行的操作。
  • Receiver:接收者,真正執行命令的對象。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。
  • Invoker:要求命令對象執行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發命令并要求命令執行相應操作的地方,也就是說相當于使用命令對象的入口。
  • Client: 創建具體的命令對象,并且設置命令對象的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發執行。

命令模式定義:將“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其它對象。命令模式也支持可撤銷的操作。

實現命令接口:

1

2

3

public abstract class Command{

????public abstract void Execute();

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class OrderCommand?implements Command{

????//持有接受者對象

????SeniorChef receiver;

????Order order;

????public OrderCommand(SeniorChef receiver, Order order){

????????this.receiver = receiver;

?????????this.order = order;

????}

????public override?void Execute(){

????????Console.WriteLine("{0}桌的訂單:", order.DiningTable);

????????foreach (string item in order.FoodDic.Keys){

????????????//通常會轉調接收者對象的相應方法,讓接收者來真正執行功能

????????????receiver.MakeFood(order.FoodDic[item],item);

????????}

????????Thread.Sleep(2000);//停頓一下 模擬做飯的過程

????????Console.WriteLine("{0}桌的飯弄好了", order.DiningTable);

????}

}

Invoker調用者,seniorChef:接收者

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class Waiter{

????ArrayList commands =?null;//可以持有很多的命令對象

????public Waiter(){

????????commands =?new ArrayList();

????}

????public void SetCommand(Command cmd){

????????commands.Add(cmd);

????}

????//提交訂單 喊 訂單來了,廚師開始執行

????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();

????????????}

????????}

????}

}

1

2

3

4

5

public class SeniorChef{

????public void MakeFood(int num,string foodName){

????????Console.WriteLine("{0}份{1}", num,foodName);

????}

}

訂單Order,封裝訂單內容,然后傳入OrderCommand,將訂單對象變為命令對象

1

2

3

4

5

6

public class Order{

????// 餐桌號碼

????public int DiningTable { set; get; }

????// food key:飯名 value:多少份

????public Dictionary FoodDic { set; get; }

}

測試端Program相當于Client角色

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

class Program{

????public static void main(string[] args){

????//program類 作為客戶端

????//創建2個order

????Order order1 =?new Order();

????order1.DiningTable =?1;

????order1.FoodDic =?new Dictionary() ;

????order1.FoodDic.Add("西紅柿雞蛋面",1);

????order1.FoodDic.Add("小杯可樂",2);

????Order order2 =?new Order();

????order2.DiningTable =?3;

????order2.FoodDic =?new Dictionary();

????order2.FoodDic.Add("尖椒肉絲蓋飯",?1);

????order2.FoodDic.Add("小杯雪碧",?1);

????//創建接收者

????SeniorChef receiver=new SeniorChef();

????//將訂單這個兩個消息封裝成命令對象

????OrderCommand cmd1 =?new OrderCommand(receiver, order1);

????OrderCommand cmd2 =?new OrderCommand(receiver, order2);

????//創建調用者 waitor

????Waitor invoker =?new Waitor();

????//添加命令

????invoker.SetCommand(cmd1);

????invoker.SetCommand(cmd2);

????//將訂單帶到柜臺 并向廚師喊 訂單來了

????invoker.OrderUp();

????Console.Read();

????}

}

總結

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

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

適用環境:
1.系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。
2.系統需要在不同的時間指定請求、將請求排隊和執行請求。
3.系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作。

4.系統需要將一組操作組合在一起,即支持宏命令。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445423.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445423.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445423.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kaggle(04)---avazu_ctr_predictor(baseline)

比賽的目的&#xff1a; 通過分析網上的系統日志和用戶行為信息&#xff0c;來預測某些網頁上項目的點擊率。是一個二分類的問題&#xff0c;只需要預測出用戶是否點擊即可最好能夠輸出某個概率&#xff0c;比如&#xff1a;用戶點擊某個廣告的概率。 比賽官網 文件信息&…

一文讀懂機器學習庫graphLab

文章目錄目錄什么是graphlab為什么使用graphlab?如何安裝graphlab?graphlab的簡單使用。目錄 什么是graphlab GraphLab 是由CMU&#xff08;卡內基梅隆大學&#xff09;的Select 實驗室在2010 年提出的一個基于圖像處理模型的開源圖計算框架&#xff0c;框架使用C語言開發實…

《Head First設計模式》第七章-適配器模式、外觀模式

適配器模式 適配器模式是什么&#xff0c;你一定不難理解&#xff0c;因為現實中到處都是。比如說&#xff1a; 如果你需要在歐洲國家使用美國制造的筆記本電腦&#xff0c;你可能需要使用一個交流電的適配器…… 當你不想改變現有的代碼&#xff0c;解決接口不適配問題&#…

《Head First設計模式》第八章筆記-模板方法模式

模板方法模式 之前所學習的模式都是圍繞著封裝進行&#xff0c;如對象創建、方法調用、復雜接口的封裝等&#xff0c;這次的模板方法模式將深入封裝算法塊&#xff0c;好讓子類可以在任何時候都將自己掛接進運算里。 模板方法定義&#xff1a;模板方法模式在一個方法中定義一…

機器學習基礎-吳恩達-coursera-(第一周學習筆記)----Introduction and Linear Regression

課程網址&#xff1a;https://www.coursera.org/learn/machine-learning Week 1 —— Introduction and Linear Regression 目錄 Week 1 Introduction and Linear Regression目錄一 介紹1-1 機器學習概念及應用1-2 機器學習分類 二 單變量的線性回歸2-1 假設函數hypothesis2…

常見8種機器學習算法總結

簡介 機器學習算法太多了&#xff0c;分類、回歸、聚類、推薦、圖像識別領域等等&#xff0c;要想找到一個合適算法真的不容易&#xff0c;所以在實際應用中&#xff0c;我們一般都是采用啟發式學習方式來實驗。通常最開始我們都會選擇大家普遍認同的算法&#xff0c;諸如SVM&a…

redis——數據結構(字典、鏈表、字符串)

1 字符串 redis并未使用傳統的c語言字符串表示&#xff0c;它自己構建了一種簡單的動態字符串抽象類型。 在redis里&#xff0c;c語言字符串只會作為字符串字面量出現&#xff0c;用在無需修改的地方。 當需要一個可以被修改的字符串時&#xff0c;redis就會使用自己實現的S…

Hotspot虛擬機的對象

創建 Step1:類加載檢查 虛擬機遇到一條 new 指令時&#xff0c;首先將去檢查這個指令的參數是否能在常量池中定位到這個類的符號引用&#xff0c;并且檢查這個符號引用代表的類是否已被加載過、解析和初始化過。如果沒有&#xff0c;那必須先執行相應的類加載過程。 Step2:分…

劍指offer(刷題1-10)--c++,Python版本

文章目錄目錄第一題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;c順序查找二分查找Python第二題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第三題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;c使用棧輔助反轉鏈表python第四題&#xff…

redis——數據結構(整數集合,壓縮列表)

4、整數集合 整數集合&#xff08;intset&#xff09;是 Redis 用于保存整數值的集合抽象數據結構&#xff0c; 可以保存 int16_t 、 int32_t 、 int64_t 的整數值&#xff0c; 并且保證集合中不會出現重復元素。 實現較為簡單&#xff1a; typedef struct intset {// 編碼方…

原 劍指offer(刷題11-20)--c++,Python版本

文章目錄目錄第11題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第12題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第13 題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第 14題&#xff1a;解題思路&#xff1a;代碼實現&…

LRU介紹和實現

LRU全稱是Least Recently Used&#xff0c;即最近最久未使用的意思。 LRU算法的設計原則是&#xff1a;如果一個數據在最近一段時間沒有被訪問到&#xff0c;那么在將來它被訪問的可能性也很小。也就是說&#xff0c;當限定的空間已存滿數據時&#xff0c;應當把最久沒有被訪問…

機器學習知識總結系列- 知識圖譜(0-0)

文章目錄目錄機器學習知識圖譜目錄 本系列的文章只是根據個人的習慣進行總結&#xff0c;可能結構與一些書籍上不太一樣&#xff0c;開始的內容比較簡單&#xff0c;會隨著后續的深入&#xff0c;不斷豐富和更新圖譜&#xff0c;同時也期待有相同興趣的朋友一起給我留言一起豐富…

跳表介紹和實現

想慢慢的給大家自然的引入跳表。 想想&#xff0c;我們 1&#xff09;在有序數列里搜索一個數 2&#xff09;或者把一個數插入到正確的位置 都怎么做&#xff1f; 很簡單吧 對于第一個操作&#xff0c;我們可以一個一個比較&#xff0c;在數組中我們可以二分&#xff0c;這…

機器學習知識總結系列- 基本概念(1-0)

文章目錄目錄1. 機器學習的定義2. 機器學習的分類2.1根據是否在人類監督下進行訓練監督學習非監督學習半監督學習強化學習2.2根據是否可以動態漸進的學習在線學習批量學習2.3根據是否在訓練數據過程中進行模式識別實例學習基于模型的學習3. 機器學習中的一些常見名詞4. 機器學習…

劍指offer(刷題21-30)--c++,Python版本

文章目錄目錄第 21題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第22 題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第23 題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第24 題&#xff1a;解題思路&#xff1a;代碼實現…

redis——對象

剛寫了redis主要的數據結構&#xff1a; 動態字符串、雙端鏈表、字典、壓縮列表、整數集合、跳表等 redis肯定不能直接使用這些數據結構來實現數據庫&#xff0c;它用這些數據庫建立了一個對象系統&#xff0c;包含&#xff1a; 字符串對象、列表對象、哈希對象、集合對象、…

劍指offer(刷題31-40)--c++,Python版本

文章目錄目錄第31 題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第32題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第33題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第34題&#xff1a;解題思路&#xff1a;代碼實現&a…

redis——數據庫

redis服務器將所有數據庫都保存在redis/redisServer中&#xff0c;數組db存放所有數據庫&#xff0c;每一項是一個redisdb結構。dbnum代表數據庫數量。 客戶端有一個指針指向當前數據庫&#xff0c;可以切換&#xff0c;也就是移動指針。 鍵空間 現在稍微介紹一下redisdb結構…

劍指offer(刷題41-50)--c++,Python版本

文章目錄目錄第41題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第42題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第43題&#xff1a;解題思路&#xff1a;代碼實現&#xff1a;cpython第44題&#xff1a;解題思路&#xff1a;代碼實現&am…