(Command Pattern)命令模式

  • 定义

    • 将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
    • 结构图:
  • 命令模式的角色划分:
    • Reciever(命令的接收者):接收命令,并知道如何进行必要的工作,实现具体的处理。任何类都可以当接收者。
    • Invoker(命令调用者):命令调用者持有一个命令对象,并在某个时间点调用命令对象的Execute()方法,将请求付诸实行。
    • Command(命令接口):Command为所有命令声明了一个接口。调用命令对象的Execute()方法,就可以让接收者进行相应的动作。这个接口也具备一个UnDo()方法,为了回滚动作使用,也可以不定义该方法。
    • ConcreteCommand(命令):ConcreateCommand定义了动作与接收者之间的绑定关系。调用者Execute()就可以发出请求,然后由ConcreateCommand调用就接收者的一个或者多个动作。
  • 应用示例:
    • 我们知道灯可以开、关,如果我们用程序去演示等的开关可以这么写:

      •  1 public class Program
         2 {
         3     public static void Main(string[] args)
         4     {
         5     Light light=new Light("light0001");
         6     // light turn on.
         7     light.On();
         8     // light turn off.
         9     light.Off();
        10     }
        11 }
        12
        13 public class Light
        14 {
        15     public string Name { get; set; }
        16
        17     public Light(string name)
        18     {
        19         this.Name = name;
        20     }
        21
        22     /// <summary>
        23     /// Turn on the light
        24     /// </summary>
        25     public void On()
        26     {
        27         Console.WriteLine("light:{0} is turn on.", this.Name);
        28     }
        29
        30     /// <summary>
        31     /// Turn off the light
        32     /// </summary>
        33     public void Off()
        34     {
        35         Console.WriteLine("light:{0} is turn off.", this.Name);
        36     }
        37 }
    • 上边的示例把灯的开、关动作调用都直接写在了Main的代码块中。但针对该例子这样写似乎没有看出有什么不妥的,但是如果是FTP的服务端接收命令解析时,我们把接收到的100左右个命令,分别定义出对应的函数到一个类中,这时就会发现这样做耦合度太高了,维护起来就不像单独On(),Off()两个动作这么轻松。
    • 试想,如果把FTP服务器端,接收到的命令拆分成不同的“命令”,有单一的“命令调用者”,这样会不会把结构划分的更清晰?

    • 备注:FTP向服务端请求命令:LS、DIR、MLS、MDIR、MKDIR、RMDIR

      LS有点像UNIX下的LS(LIST)命令:

      DIR相当于LS-L(LIST-LONG);

      MLS只是将远端某目 录下的文件存于LOCAL端的某文件里;

      MDIR相当于MLS;

      MKDIR像DOS下的MD(创建子目录)一样:

      RMDIR像DOS下的RD(删除子目录)一样。

    • 下边我们将上边的例子Light按照Command设计模式来改写,看下效果:
      • 命令接口:Command

        1 public interface ICommand
        2 {
        3
        4     void Execute();
        5
        6 }
      • 命令的接收者:Reciever
        •  1 public class Light
           2 {
           3     public string Name { get; set; }
           4
           5     public Light(string name)
           6     {
           7         this.Name = name;
           8     }
           9
          10     /// <summary>
          11     /// Turn on the light
          12     /// </summary>
          13     public void On()
          14     {
          15         Console.WriteLine("light:{0} is turn on.", this.Name);
          16     }
          17
          18     /// <summary>
          19     /// Turn off the light
          20     /// </summary>
          21     public void Off()
          22     {
          23         Console.WriteLine("light:{0} is turn off.", this.Name);
          24     }
          25 }
      • 命令的封装者:ConcreateCommand

         1 public class LightOnCommand : ICommand
         2 {
         3     private Light light;
         4
         5     public LightOnCommand(Light light)
         6     {
         7         this.light = light;
         8     }
         9
        10     public void Execute()
        11     {
        12         this.light.On();
        13     }
        14 }
      • 命令的封装者:ConcreateCommand

         1 public class LightOffCommand : ICommand
         2 {
         3     private Light light;
         4
         5     public LightOffCommand(Light light)
         6     {
         7         this.light = light;
         8     }
         9
        10     public void Execute()
        11     {
        12         this.light.Off();
        13     }
        14 }
      • 命令的封装者:命令的Invoker

         1 public class CommandControl
         2 {
         3     private ICommand command;
         4
         5     public CommandControl() { }
         6
         7     public void SetCommand(ICommand command)
         8     {
         9         this.command = command;
        10     }
        11
        12     public void ButtonPresssed()
        13     {
        14         this.command.Execute();
        15     }
        16 }
      • 客户端:client

         1 class Program
         2 {
         3     static void Main(string[] args)
         4     {
         5         CommandControl control = new CommandControl();
         6         Light light = new Light("light_001");
         7         LightOnCommand lightOn = new LightOnCommand(light);
         8         LightOffCommand lightOff = new LightOffCommand(light);
         9
        10         control.SetCommand(lightOn);
        11         control.ButtonPresssed();
        12
        13         control.SetCommand(lightOff);
        14         control.ButtonPresssed();
        15
        16         control.SetCommand(lightOn);
        17         control.ButtonPresssed();
        18
        19         control.SetCommand(lightOff);
        20         control.ButtonPresssed();
        21
        22         Console.ReadKey();
        23     }
        24 }
  • 应用场景:
    •   多级UnDo操作的应用场景;

      •   如何实现多层撤销操作?
      •   首先,不要只是记录最后一个被执行的命令,而使用一个堆栈记录操作过程的每一个命令。
      •   然后,不管什么时候操作了什么,都可以从堆栈中取出最上层的命令,然后调用它的UnDo()方法。
    •  命令可以将运算块打包(一个接收者和一组动作),让后将它传来传去,就像是一般的对象一样。现在,即使在命令对象被创建许久之后,运算依然可以被调用。事实上,它甚至可以在不同的线程中被调用。我们可以衍生一些应用,例如:日程安排(Scheduler)、线程池、工作队列等。
    • 日志请求:某些应用需要我们将所有的动作都记录在日志中,并能在系统死机之后,重新调用这些动作恢复到之前的状态。通过两个方法 Store(),Load(),命令模式就能够支持这一点。
时间: 2024-11-10 07:50:18

(Command Pattern)命令模式的相关文章

设计模式(六)The Command Pattern 命令模式

摘要 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作 问题引入 近来,智能家居闹得比较凶,这里我们想要实现一个简单的自动家居,由一个遥控器来完成电灯.音响.风扇的开关. 模式定义 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作 认识模式 对于这个模式我最欣赏的就是他将"做什么"与"怎么做"的问题或者说是"动作的请求者

Command Pattern 命令模式

定义: 命令模式将‘请求’封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作. 类图 如上图所示:Command类是用来声明执行操作的接口:ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute:Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者:Invoker类,要求该命令执行这个命令. 命令模式实现: /** *声明执行者接口 */ public abstract

[Design Pattern] Command Pattern 命令模式

发现公司的代码好像有用到 Command Pattern,回顾重温下. Command Pattern 的类图结构如下: 参考 <Head First Design Patterns(英文版)>P245 绘制 我所理解的 Command Pattern 如图. caller, action, subject 分别对于类图中的 Invoker, Command, Receiver, 他们都可以由使用者 Client 进行配置 参考资料: Head First Design Pattern. 推荐

从王者荣耀看设计模式(九.命令模式)

从王者荣耀看设计模式(命令模式) 一.简介 王者荣耀是一款团队竞技游戏.良好的团队信息交流在一定程度上能帮助队伍取得胜利.为了保证游戏的流畅性与便捷性,王者荣耀提供了快捷交流机制,在王者小地图旁边有几个快捷聊天按钮(开始撤退,发起进攻,请求结合),玩家可通过点击快捷聊天按钮发出相应命令与队友进行交流 二.命令模式 命令模式(Command Pattern):命令模式是一种高内聚的模式,将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作.

读书笔记之设计模式-命令模式

行为型:Command(命令模式) 命令模式: 目的:其实一般设计模式就是为了解耦.也没什么特别的,命令模式实际上就是将命令的请求者和命令的执行者解耦. 白话:领导说了,让把这个月的项目计划压缩到三个礼拜完成,还说了:"不管你用什么办法".这句“不管你用什么办法”就是我们所说的解耦.我不需要关心你怎么去做,我只要你能实现我想达到的目的. 模式结构:一般包含下面几个部分. Client:客户 Invoker:命令触发者 Command:命令 ConcreteCommand:具体命令实现

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

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

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

夏日的夜晚,大街上总是热闹非凡,人们都喜欢约三五好友去吃烧烤喝啤酒,所谓吃着烤串儿,还唱着歌儿,那感觉就一个字--爽. 在街上溜达,突然发现一个烧烤摊人不多,于是你就上前对老板说:来10串羊肉串,3串鸡翅--.说完之后,你就站在边上等,这时你发现,人越来越多,之间大家七嘴八舌跟老板说自己的要求,明显看到老板有些手足无措.首先老板要记住谁先来的谁后来的,谁给钱了谁没给钱,谁不要放辣椒--等等,太多的问题接踵而至,而且那么多人都在那里盯着老板烤串,这样就引起了挑剔,哪一串多了,哪一串少了什么的,真的

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

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

Java设计模式の命令模式

意图: 将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化:对请求排队或记录日志,以及支持可撤销的操作 动机: 将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来. 效果: 1).command模式将调用操作的对象和实现该操作的对象解耦 2).可以将多个命令装配成一个复合命令,复合命令是Composite模式的一个实例 3).增加新的command很容易,无需改变已有的类 适用性: 1).抽象出待执行的动作以参数化某对象 2).在不同的时刻指定.排列和执行请求.如请求队列 3)