烤羊肉串引来的思考——命令模式

2024-05-25 16:18

本文主要是介绍烤羊肉串引来的思考——命令模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    夏日的夜晚,大街上总是热闹非凡,人们都喜欢约三五好友去吃烧烤喝啤酒,所谓吃着烤串儿,还唱着歌儿,那感觉就一个字——爽。

 

    在街上溜达,突然发现一个烧烤摊人不多,于是你就上前对老板说:来10串羊肉串,3串鸡翅……。说完之后,你就站在边上等,这时你发现,人越来越多,之间大家七嘴八舌跟老板说自己的要求,明显看到老板有些手足无措。首先老板要记住谁先来的谁后来的,谁给钱了谁没给钱,谁不要放辣椒……等等,太多的问题接踵而至,而且那么多人都在那里盯着老板烤串,这样就引起了挑剔,哪一串多了,哪一串少了什么的,真的很是混乱。

    于是你你选择了去不远处的一家烧烤店,坐下后,直接给服务员说了自己要吃什么吃多少,服务员在订单上记下之后,直接将订单送往后厨,然后招待其他刚进来的顾客。作为一个程序员的你,此时此刻陷入了沉思……

    今晚这两种情况恰好说明了一个软件设计中设计模式,就是标题提到的命令模式,我们来看看如何将现实情况映射到命令模式。

首先第一种情况,烧烤摊的经营模式我们可以对其进行抽象,得到如下类图:


     结构图很简单,就两个类,但是正因为简单,其隐含的问题就太多了.单纯地从编程的角度看,客户是"行为的请求者",而烤串老板即为"行为的实现者",上面的那种情况下,两者的耦合性很高,这在编程中是大忌,而且如果行为请求者要撤销自己的请求,这种紧耦合的关系实在是很麻烦.那么如何改进呢?

我们再来看看对烧烤店的情况进行的抽象,其结构图如下:


     从上面的类图中可以看到,我们加入了一个服务员类,从而使客户和烤串者解耦合,服务员一方面要从客户那里接受订单,另一方面就是通知后厨师傅执行客户的要求.我们结合具体的代码实现来说明类图中的关系时如何在代码中实现的,至于第一个类图的代码实现由于比较简单,就留给读者去实现吧,这里不再赘述.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication1
{//客户端代码实现class Program{static void Main(string[] args){//开店前的准备Barbecuer boy = new Barbecuer();Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);Waiter girl = new Waiter();//开门营业,顾客点菜girl.SetOrder(bakeMuttonCommand1);girl.SetOrder(bakeChickenWingCommand1);//点菜完毕,通知厨房做菜girl.Notify();Console.Read();}}//烤串者类public class Barbecuer{public void BakeMutton(){Console.WriteLine("烤羊肉串");}public void BakeChickenWing(){Console.WriteLine("烤鸡翅");}}//抽象命令类public abstract class Command{protected Barbecuer receiver;public Command(Barbecuer receiver){this.receiver = receiver;}abstract public void ExcuteCommand();}//具体命令类//烤羊肉串命令class BakeMuttonCommand:Command {public BakeMuttonCommand (Barbecuer receiver):base(receiver ){}public override void ExcuteCommand(){receiver.BakeMutton();}}//烤鸡翅命令class BakeChickenWingCommand : Command{public BakeChickenWingCommand(Barbecuer receiver): base(receiver){ }public override void ExcuteCommand(){receiver.BakeChickenWing();}}//服务员类//public class Waiter//{//    private Command command;//    public void SetOrder(Command command)//    {//        this.command = command;//    }//    public void Notify()//    {//        command.ExcuteCommand();//    }//}//改写后的服务员类*******************************************************************************public class Waiter{private IList<Command> orders = new List<Command>();//设置订单public void SetOrder(Command command){if (command.ToString() == "命令模式.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.ExcuteCommand();}}}
}

     首先我们看服务员类和抽象命令类之间是聚合关系,为什么呢?很简单就是服务员可以接受各种各样的命令,而服务员和各个命令类各自是相互独立的,因此是一种聚合关系.代码中我们在服务员类中声明一个存放具体命令的容器(List类型),然后将具体的命令类的实例作为其方法的参数,以便对其进行操作.

     其次是抽象命令类和具体的命令类之间的继承关系,这个很简单应该不用多少了,就是在创建具体类的时候在类名的后面加上:后跟上父类类名(C#语言).

     再者是烤肉串者和具体命令类之间的依赖关系,这个我们在定义具体类的时候,类的构造方法的参数设为烤串者,这样就表达了,具体命令类的执行要依赖于具体的实现者,然后在方法体中通过烤串者类的实例对象调用烤串者的方法,完成具体命令要求的行为和操作.

     最后是客户端类和服务员类以及烤肉串者类之间的关联关系,这种关系是通过在客户端类中添加服务员类和烤串者类的引用来表现的,就是在客户端的代码中实例化一个烤串者类的具体对象和一个服务员类的具体对象.

     以上就是类图中各种关系在代码中的实现方法,我们可以用这样的方式去分析其他设计模式的结构图中的各种关系,这样我们在类图和代码之间的转换就会游刃有余,胸有成竹了.

   最后给出命令模式的定义:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。我们可以对照上面的例子来理解命令模式的定义,这样就能够形象的理解命令模式到底是怎么一回事了。

这篇关于烤羊肉串引来的思考——命令模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1002003

相关文章

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

PowerShell中15个提升运维效率关键命令实战指南

《PowerShell中15个提升运维效率关键命令实战指南》作为网络安全专业人员的必备技能,PowerShell在系统管理、日志分析、威胁检测和自动化响应方面展现出强大能力,下面我们就来看看15个提升... 目录一、PowerShell在网络安全中的战略价值二、网络安全关键场景命令实战1. 系统安全基线核查

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一