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

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

相关文章

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

使用mvn deploy命令上传jar包的实现

《使用mvndeploy命令上传jar包的实现》本文介绍了使用mvndeploy:deploy-file命令将本地仓库中的JAR包重新发布到Maven私服,文中通过示例代码介绍的非常详细,对大家的学... 目录一、背景二、环境三、配置nexus上传账号四、执行deploy命令上传包1. 首先需要把本地仓中要

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

Windows命令之tasklist命令用法详解(Windows查看进程)

《Windows命令之tasklist命令用法详解(Windows查看进程)》tasklist命令显示本地计算机或远程计算机上当前正在运行的进程列表,命令结合筛选器一起使用,可以按照我们的需求进行过滤... 目录命令帮助1、基本使用2、执行原理2.1、tasklist命令无法使用3、筛选器3.1、根据PID

Linux系统之authconfig命令的使用解读

《Linux系统之authconfig命令的使用解读》authconfig是一个用于配置Linux系统身份验证和账户管理设置的命令行工具,主要用于RedHat系列的Linux发行版,它提供了一系列选项... 目录linux authconfig命令的使用基本语法常用选项示例总结Linux authconfi

linux打包解压命令方式

《linux打包解压命令方式》文章介绍了Linux系统中常用的打包和解压命令,包括tar和zip,使用tar命令可以创建和解压tar格式的归档文件,使用zip命令可以创建和解压zip格式的压缩文件,每... 目录Lijavascriptnux 打包和解压命令打包命令解压命令总结linux 打包和解压命令打

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

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

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

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

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