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

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

相关文章

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

PHP执行php.exe -v命令报错的解决方案

《PHP执行php.exe-v命令报错的解决方案》:本文主要介绍PHP执行php.exe-v命令报错的解决方案,文中通过图文讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录执行phpandroid.exe -v命令报错解决方案执行php.exe -v命令报错-PHP War

CentOS系统使用yum命令报错问题及解决

《CentOS系统使用yum命令报错问题及解决》文章主要讲述了在CentOS系统中使用yum命令时遇到的错误,并提供了个人解决方法,希望对大家有所帮助,并鼓励大家支持脚本之家... 目录Centos系统使用yum命令报错找到文件替换源文件为总结CentOS系统使用yum命令报错http://www.cppc

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)