zoukankan      html  css  js  c++  java
  • [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 }
    View Code

    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();
                    }
                }
            }
        }
    }
    Waitor
     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 }
    SeniorChef

    订单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 }
    Order

    测试端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 设计模式

    百度百科

     

  • 相关阅读:
    java核心技术记录之集合
    Set的非重复判断是根据什么判断的
    struts2-2.3.4.1的struts-default.xml源码
    纯代码搭建项目框架
    初始化项目
    项目部署
    使用estimatedRowHeight的优缺点
    懒加载
    闭包
    Swift 类的构造函数
  • 原文地址:https://www.cnblogs.com/wolf-sun/p/3618911.html
Copyright © 2011-2022 走看看