博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Head First设计模式]餐馆中的设计模式——命令模式
阅读量:6323 次
发布时间:2019-06-22

本文共 5638 字,大约阅读时间需要 18 分钟。

系列文章

实例

这里采用书中餐厅订餐的例子。餐厅订餐的例子还是比较简单的,也比较好理解,书中的遥控器的例子,太长了,能把人绕晕,图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.命令模式{    ///     /// Command为所有命令声明一个接口,调用命令对象的excute方法    /// 就可以让接收者进行相关的动作,    ///     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     /// 11     /// 具体的命令12     /// 13     public class OrderCommand : Command14     {15         /// 16         ///持有接受者对象17         /// 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.命令模式{    ///     /// 美女服务员类 这里作为调用者Invoker的角色    ///     public class Waitor    {        ArrayList commands = null;//可以持有很多的命令对象        public Waitor()        {            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();                }            }        }    }}
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     /// 10     /// 资深大厨类 是命令的Receiver11     /// 12     public class SeniorChef13     {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     /// 10     /// 订单11     /// 12     public class Order13     {14         /// 15         /// 餐桌号码16         /// 17         public int DiningTable { set; get; }18         /// 19         /// food  key:饭名 value:多少份20         /// 21         public Dictionary
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 Program10     {11         static void Main(string[] args)12         {13             //program类 作为客户端14             //创建2个order15             Order order1 = new Order();16             order1.DiningTable = 1;17             order1.FoodDic = new Dictionary
() ;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
();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 //创建调用者 waitor32 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 设计模式

百度百科

 

转载于:https://www.cnblogs.com/wolf-sun/p/3618911.html

你可能感兴趣的文章
如何在Linux上搭建一个基于Web的轻型监控系统
查看>>
linux基础命令使用
查看>>
zabbix简单检测
查看>>
我的友情链接
查看>>
CCNP学习笔记10-路由部分--BGP 前缀列表
查看>>
关于导航视图无法隐藏的问题:self.navigationItem.rightBarButtonItem.customView.hidden = YES;无效...
查看>>
other模块的网络请求业务封装工具类
查看>>
Android studio取消上次打开的工程
查看>>
Cocos2dx-3.0-rc0版本Lua的配置与使用
查看>>
计算机编程软件C语言的介绍
查看>>
调用谷歌翻译API(FREE)的java代码
查看>>
Windows进程崩溃问题定位方法
查看>>
程序员如何让自己 Be Cloud Native - 配置篇
查看>>
Django学习系列之Form基础
查看>>
每天一个linux命令(35):ln 命令
查看>>
SQL Server各个版本之间的差异
查看>>
方差分析中的多重比较
查看>>
SPI总线协议
查看>>
如何拆笔记本键盘(组图)
查看>>
lua install
查看>>