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

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

在街上溜达,突然发现一个烧烤摊人不多,于是你就上前对老板说:来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#语言).

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

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

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

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

时间: 2024-08-27 01:42:53

烤羊肉串引来的思考——命令模式的相关文章

【行为型模式】《大话设计模式》——读后感 (15)烤羊肉串引来的思考?——命令模式

命令模式:将一个请求封装为一个对象,从而使得你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作[DP] 先看代码吧: Receiver: package com.sjmx.command; public class Receiver { public void doSomething(){ System.out.println("接受者-业务逻辑处理"); } } Command: package com.sjmx.command; public abst

第16章 行为型模式—命令模式

1. 命令模式(Command Pattern)的定义 (1)定义 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. ①封装请求:抽象出需要执行的动作,封装成对象(有统一的接口). ②参数化:可以用不同的命令对象,去参数化配置客户的请求.(即,将命令对象作为参数去供Invoker调用). (2)命令模式的结构和说明 ①Command:定义命令的接口,声明执行的方法 ②ConcreteCommand:命令接口实现对象,是“虚”的实现

码农小汪-设计模式之-命令模式

大话设计模式的例子讲的非常的好,理解起来也方便!有时候忘了.想到这些特殊的例子感觉就是特别爽. 烤羊肉串带来的思考! 路边摊羊肉串: 老板,我这里排的比较先啊,我最先给钱.老板这个没有熟啊.我的是 辣的啊!老板没有放盐啊!场面混乱,已经分不清谁是谁的啊,人太多了.烤肉的质量也受到了影响,心情不好也就不好啊.烤肉的人心情受到了顾客的影响. 店面的烤肉 服务员,给我来两串羊肉串,2鸡翅,啤酒两瓶. 鸡翅没得啦,点别的吧,肉精吧.辣一点. 两者的比较啊: 路边的生意不稳定,往往就是那几个时间,客源不固

【游戏设计模式】之二 实现撤消重做、回放系统的神器:命令模式

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/52663057 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 这篇文章将与大家一起探索游戏开发中命令模式的用法. 命令模式的成名应用是实现诸如撤消,重做,回放,时间倒流之类的功能.如果你想知道<Dota2>中的观战系统.<魔兽争霸3>中的录像系统.<守望先锋>

C#面向对象设计之——命令模式(十五)

一.前言 命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,另外对请求排队或记录请求日志,以及支持可撤销的操作. 二.结构图 三.实例代码 namespace 命令模式 { class Program { static void Main(string[] args) { //开店前的准备 Barbecuer boy = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); Co

java设计模式之命令模式

学校中.生活中.社会中总是会存在一定的阶层,虽然我们很多人都不可认可阶层的存在.命令这一词也就在阶层中诞生.家长命令孩子,老师命令学生,领导命令小娄娄.这些都在我们的生活存在的东西,相信这一个模式学习起来也会比较简单的.这次我们就举一个领导命令员工的例子来学习命令模式. 工作中领导经常会叫(命令)你去做一些事情,但是领导并不关心你怎么做的,只需要知道你做的结果就好了.怎么做是你自己的事情,做不好就等着加班吧(开玩笑的,一般都会说自己自愿的,哈哈),做的好功劳也不好是你的,哈哈好像有点小黑暗.一般

大话设计模式C++实现-第23章-命令模式

一.UML图 二.概念 命令模式(Command):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求进行排队或记录请求日志,以及支持可撤销的操作. 三.说明 角色: (1)Command类:用来声明执行操作的接口. (2)ConcreteCommand类:将一个接收者对象绑定与一个动作,调用接收者相应的操作,以实现Excute. (3)Invoker类:要求该命令执行这个请求. (4)Receiver类:知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者.

《大话设计模式》学习笔记19:命令模式

烧烤店点餐示例: 实现1: 1.Receiver: public class Barbecuer { public void BakeMutton() { Console.WriteLine("烤羊肉串!"); } public void BakeChickenWing() { Console.WriteLine("烤鸡翅!"); } } 2.Command: public abstract class Command { protected Barbecuer r

(十二)命令模式详解(故事版) .

背景:小左是魔都某公司技术部的一名屌丝程序猿,每天的工作就是维护一个20世纪的古董级项目,由于公司不大,所以公司很多制度不太完善,导致小左每天都郁闷异常,只是靠偶尔的在刚毕业的小小美女程序媛旁边露一手,来丰富自己的精神生活. 某一天下午一点半,阴. 小左正趴在桌子上,迷迷糊糊想着某些个不切实际的美梦,突然QQ上"滴滴滴"的声音,将本就只是半梦半醒的小左给吵醒了.无奈之下,小左只好懒懒散散的抬起头,打开了QQ消息. 业务人员A:"小左啊,我们的XX列表需要加一个显示项和一个搜索