[Head First设计模式]餐馆中的设计模式——命令模式

系列文章

[Head First设计模式]山西面馆中的设计模式——装饰者模式

[Head First设计模式]山西面馆中的设计模式——观察者模式

[Head First设计模式]山西面馆中的设计模式——建造者模式

[Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

[Head First设计模式]一个人的平安夜——单例模式

[Head First设计模式]抢票中的设计模式——代理模式

[Head First设计模式]面向对象的3特征5原则

[Head First设计模式]鸭子模型——策略模式

[Head First设计模式]云南米线馆中的设计模式——模版方法模式

实例

这里采用书中餐厅订餐的例子。餐厅订餐的例子还是比较简单的,也比较好理解,书中的遥控器的例子,太长了,能把人绕晕,图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.命令模式
{
    /// <summary>
    /// Command为所有命令声明一个接口,调用命令对象的excute方法
    /// 就可以让接收者进行相关的动作,
    /// </summary>
    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     /// <summary>
11     /// 具体的命令
12     /// </summary>
13     public class OrderCommand : Command
14     {
15         /// <summary>
16         ///持有接受者对象
17         /// </summary>
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 }

Waitor:Invoker调用者,seniorChef:接收者 厨师类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wolfy.命令模式
{
    /// <summary>
    /// 美女服务员类 这里作为调用者Invoker的角色
    /// </summary>
    public class Waitor
    {
        ArrayList commands = null;//可以持有很多的命令对象
        public Waitor()
        {
            commands = new ArrayList();
        }
        public void SetCommand(Command cmd)
        {
            commands.Add(cmd);
        }
        /// <summary>
        /// 提交订单 喊 订单来了,厨师开始执行
        /// </summary>
        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();
                }
            }
        }
    }
}

 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     /// <summary>
10     /// 资深大厨类 是命令的Receiver
11     /// </summary>
12     public class SeniorChef
13     {
14         public void MakeFood(int num,string foodName)
15         {
16             Console.WriteLine("{0}份{1}", num,foodName);
17         }
18     }
19 }

订单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     /// <summary>
10     /// 订单
11     /// </summary>
12     public class Order
13     {
14         /// <summary>
15         /// 餐桌号码
16         /// </summary>
17         public int DiningTable { set; get; }
18         /// <summary>
19         /// food  key:饭名 value:多少份
20         /// </summary>
21         public Dictionary<string, int> FoodDic { set; get; }
22     }
23 }

测试端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 Program
10     {
11         static void Main(string[] args)
12         {
13             //program类 作为客户端
14             //创建2个order
15             Order order1 = new Order();
16             order1.DiningTable = 1;
17             order1.FoodDic = new Dictionary<string, int>() ;
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<string, int>();
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             //创建调用者 waitor
32             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 设计模式

百度百科

 

博客地址: http://www.cnblogs.com/wolf-sun/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。

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

时间: 2024-09-23 02:49:26

[Head First设计模式]餐馆中的设计模式——命令模式的相关文章

.NET设计模式(17):命令模式(Command Pattern)

意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作.[GOF <设计模式>] 结构图 Command模式结构图如下: 图1 Command模式结构图 生活中的例子 Command模式将一个请求封装为一个对象,从而使你可以使用不同的请求对客户进行参数化.用餐时的账单是Command模式的一个例子.服务员接受顾客的点单,把它记在账单上封装.这个点单被排队等待烹饪.注意这里的"账单"是不依赖于菜单的,它可以被不同

设计模式系列之十:命令模式

前言 命令模式属于行为型设计模式.所谓命令,肯定有命令的发送者以及命令的接收者,命令模式则是命令本身封装成一个对象,从而使得命令接收者可以根据接收到的命令让不同的命令执行者执行具体的命令,使用命令模式可以让命令请求者排队并记录命令日志.命令模式可以使你可用不同的请求对客户参数化.很显然,通过使用命令模式可以较容易地设计一个命令队列,最重要的是命令模式把命令请求的对象与具体执行命令的对象分隔开了,这样具体的命令执行者与命令请求者之间的耦合度就降低了.使用命令模式可以很容易添加命令撤销的操作,但是一

C++设计模式编程中使用Bridge桥接模式的完全攻略_C 语言

桥接模式将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式典型的结构图为: 在桥接模式的结构图中可以看到,系统被分为两个相对独立的部分,左边是抽象部分,右边是实现部分,这两个部分可以互相独立地进行修改:例如上面问题中的客户需求变化,当用户需求需要从 Abstraction 派生一个具体子类时候,并不需要像上面通过继承方式实现时候需要添加子类 A1 和 A2 了.另外当上面问题中由于算法添加也只用改变右边实现(添加一个具体化子类),而右边

总结JavaScript设计模式编程中的享元模式使用_基础知识

享元模式不同于一般的设计模式,它主要用来优化程序的性能,它最适合解决大量类似的对象而产生的性能问题.享元模式通过分析应用程序的对象,将其解析为内在数据和外在数据,减少对象的数量,从而提高应用程序的性能. 基本知识 享元模式通过共享大量的细粒度的对象,减少对象的数量,从而减少对象的内存,提高应用程序的性能.其基本思想就是分解现有类似对象的组成,将其展开为可以共享的内在数据和不可共享的外在数据,我们称内在数据的对象为享元对象.通常还需要一个工厂类来维护内在数据. 在JS中,享元模式主要有下面几个角色

Java设计模式(十八)----命令模式

命令模式 一. 概念 二. 结构 三. 具体案例 四. 宏命令 五. 命令模式优点 引子 在程序设计中,经常设计到一个对象需要请求另外一个对象调用其方法达到某种目的,如果请求这不希望或不直接和被请求者打交道,既请求者不包含被请求者的引 用,那么就可以使用命令模式.例如在军队中,指挥官请求三连偷袭敌人,但是指挥官不希望或无法直接与三连取得联系,那么可以将该请求形成一个命令,该命令 的核心是让三连偷袭敌人.只要能让该命令被执行,就会实现偷袭敌人的目的. 命令模式是关于怎样处理一个对象请求到另一个对象

实例讲解PHP设计模式编程中的简单工厂模式_php实例

简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式.简单工厂模式是由一个工厂对象决定创建出那一种产品类的实例. 1.工厂模式的几种形态工厂模式专门负责将大量有共同接口的类实例化.工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类.工厂模式有以下几种形态: (1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern). (2)工厂方法(Factory Meth

C++设计模式编程中Template Method模板方法模式的运用_C 语言

准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模版方法模式的用意. 很多人可能没有想到,模版方法模式实际上是所有模式中最为常见的几个模式之一,而且很多人可能使用过模版方法模式而没有意识到自己已经使用了这个模式.模版方法模式是基于继承的代码复用的基本技术,模版方法模式的结构和用法也是面向对象设计的核心. 模版方法模式需要开发抽象类和具体子类的设计师之间的协作

举例讲解Java设计模式编程中Decorator装饰者模式的运用_java

概念 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型. 你可以用一个或多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合 ,可以用装饰过的对象代替它. 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的. 对象可以在任何时候被装饰,所以可以在运行时动态地.不限量地用你喜欢的装饰者来装饰 对象. 在Java中,io包下的很多类就是典型的装饰

Ruby设计模式编程中使用Builder建造者模式的实例_ruby专题

先来复习一下设计模式的基本概念:定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要重新定一个建造者就可以了.实用范围1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 2.当构造过程必须允许被构造的对象有不同表示时.角色在这样的设计模式中,有以下几个角色: 1.builder:为创建一个产品对象的各个部件指定抽象接口. 2.ConcreteBuilder:实现Builder