设计模式15――行为型模式之命令模式

2014-11-24 02:36:13 · 作者: · 浏览: 1

定义:命令模式(Command Pattern),将一个请求封闭成一个对象,从而使你可用不同的请求对客户进行参数化;对请求排除或记录请求日志,以及支持可撤销的操作。

类型:行为型模式。

概述:

命令模式,被《Head First设计模式》列为常见的设计模式之一,而且光看类图,感觉很简单。可是真正要去运用的时候,往往会发现无从下手。因为你不知道什么时候该使用命令模式。任何关联的两个类,你发现居然都可以使用命令模式。但是使用了之后,发现代码理解起来似乎变得更复杂了。本来比较简单,并且耦合并不严重的两个类,再加进来一个命令类,反倒更复杂了。如果严格依照迪米特法则,差不多任何两个有关联的类都似乎需要一个中介类来减少它们的耦合。如果极端地这样做,必将出现非常多的中介类,反倒将程序弄得更复杂了。

在代码发展的初期,我们很难发现需要使用哪种模式。其实这个时候,我们也不必纠结该使用哪种模式,我们先把基本的对象抽象好就行了。待代码发展到比较复杂开始需要重构代码时,这个时候就是设计模式上场的时候了。重构代码时,发现两个类严重耦合,这个时候就得考虑使用何种方式解耦了。

创建型模式和结构型模式,更多地考虑代码的复用,而行为型模式更多地考虑代码的解耦。命令模式的作用,就是解耦的,主要解决那些“发出命令”和“响应命令”两者之间的耦合。所谓术业有专攻,这句话在软件设计体现得淋漓尽致。每个人都做自己擅长的事情,把不擅长的事情独立出来,交给专门的人来做。

因为命令模式是抽象出命令的, 所以那些需要处理多次命令的,例如记录,删除,查找等操作命令的时候,就可以使用命令模式。

到处是点菜下订单这样的示例,虽然这是个非常好的应用命令模式的示例,但是被大家过多讲述。所以这里,我举一个新的示例。小机床作坊,老板(Boss)加10位操作工(A~J)的干活,主要生产螺丝、轴承等等。

类图:

\

参与者:

  1. Client,创建Boss、Workers以及具体的Command。
  2. Boss,也即Invoker,调用命令。
    1. ScrewCMD,BearingCMD,具体的命令,告诉Workers如何相应的生产。
      1. Workers,也即Receiver,接收命令并响应具体的命令。

        示例代码:

         1 using System;
         2 using System.Collections.Generic;
         3 using System.Text;
         4 
         5 namespace CMD
         6 {
         7     abstract class Command
         8     {
         9         protected Workers workers;
        10 
        11         public Command(Workers _workers)
        12         {
        13             this.workers = _workers;
        14         }
        15 
        16         abstract public void Execute();
        17     }
        18 
        19     class ScrewCMD : Command
        20     {
        21         public ScrewCMD(Workers _workers) : base(_workers) { }
        22 
        23         public override void Execute()
        24         {
        25             workers.ProductScrew();
        26         }
        27     }
        28 
        29     class BearingCMD : Command
        30     {
        31         public BearingCMD(Workers _workers) : base(_workers) { }
        32 
        33         public override void Execute()
        34         {
        35             workers.ProductBearing();
        36         }
        37     }
        38 
        39     class Workers
        40     {
        41         public void ProductScrew()
        42         {
        43             Console.WriteLine("生产螺丝!");
        44         }
        45 
        46         public void ProductBearing()
        47         {
        48             Console.WriteLine("生产轴承.");
        49         }
        50     }
        51 
        52     class Boss
        53     {
        54         private Command command;
        55 
        56         public void SetCommand(Command command)
        57         {
        58             this.command = command;
        59         }
        60 
        61         public void ExecuteCommand()
        62         {
        63             command.Execute();
        64         }
        65     }
        66 
        67     class Program
        68     {
        69         static void Main(string[] args)
        70         {
        71             Workers workers = new Workers();
        72             Command screw = new ScrewCMD(workers);
        73             Command bearing = new BearingCMD(workers);
        74             Boss boss = new Boss();
        75 
        76             // 生产螺丝的命令
        77             boss.SetCommand(screw);
        78             boss.ExecuteCommand();
        79 
        80             // 生产轴承的命令
        81             boss.SetCommand(bearing);
        82             boss.ExecuteCommand();
        83 
        84             Console.Read();
        85         }
        86     }
        87 }


        适用性:

        1. 抽象出待执行的动作以参数化某对象。
        2. 在不同的时刻指定、排列和执行请求。
        3. 支持取消操作
        4. 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
        5. 用构建在原语操作上的高层操作构造一个系统。

          优缺点:

          1. 优点,降低命令发起者与命令接受者之间的耦合,将复杂的命令过程独立出来。
          2. 缺点,如果命令过多,管理命令本身会变得复杂起来。

            参考资料:

            1. 《设计模式――可复用面向对象软件基础》
            2. 《大话设计模式》
            3. 《Head First设计模式》