为什么要使用command模式

意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及

        支持可撤消的操作。

    很迷惑,看了之后不知道在说什么。如果这样说,我想理解的更清楚些 。本模式把“发出命令的责任和执行命令的责任分割开,委派给不同的对象”。或者我们也可以这样理解: “请求”即 方法,命令 如“打球” 这就是一个方法,一个请求。我们可以把这个方法提到类的层次,封装为一个对象。当然了有了对象我们就可以把他们排队 可以 对客户进行参数化。关于“参数化” 这点也很难理解, 在C语言里我们经常使用回调函数。回调的基本思想就是用系统提供一些接口函数,将某个其他函数的地址作为其参数之一,可以通过该地址对这个函数进行调用,而被调用的函数就是我们通常所说的回调函数了。在Command模式中做为参数的函数地址就可以用Command对象来替代。即方法提到了类的层次 ,呵呵 又说了一遍。

为什么使用?

1:发出命令以及决定命令何时执行与 命令到底是由谁来执行,怎么执行 显然是两个不同的逻辑。如果把他们放在

     一起显然是不合适的,易导致职责不单一,逻辑不清晰。所以需要委派给不同的对象,使他们松耦合。

2:本模式通过引入一个command 中间层,解耦了发出命令和执行命令的逻辑,正因为有了这个中间层我们才可以

    在调用者角色中做很多事情,比如延迟命令的执行、为执行的命令记录日志、撤销命令执行等等。

命令模式涉及到的角色:

  • 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
  • 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。
  • 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。
  • 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
  • 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。

总结:

     1:在应用的过程中可以省略一些不重要的角色。比如,如果只有一个执行者或者执行的逻辑非常简单的话,可以

         把执行的逻辑合并到具体命令角色中;如果我们并不需要使用调用者来做额外的功能,仅仅是希望通过命令模式

         来解除客户端和接受者之间耦合的话可以省略调用者角色。

     2:命令角色的逻辑可以很复杂也可以很简单。这是两个极端。

     3:我们可以对命令利用组合模式进行组合。

     4:如果不需要对命令做额外操作,比如撤消等功能。那么这个时候命令类也就退化为一个执行者。

     5:命令角色除了封装一些不应该放在执行者角色的逻辑(如命令对象可以把状态存储起来,等到客户端需要撤销命

         令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供

         客户端在需要时,再重新实施命令效果。这些方法/逻辑是不应该放在执行者角色的)外,还提供一个一致简化的

         接口方便调用,因为具体执行者的方法接口可能是多种多样的。

    6:“何时执行及是否执行”这个逻辑确实如 吕振宇所说,应该放在请求者(Invoker)角色里面,这点阎宏的太白金星

          宣悟空上天那个例子容易误导。

    7:实际中这个模式应用的很灵活,因此并不应该死套该模式,我们的目标是优雅的设计(灵活 逻辑清晰 消除重复)

         因此对于具体问题具体应用该模式 该简化的部分就简化 否则有过度设计,死搬硬套之臭味,对于该臭味我们可

         以应用面向对象的设计原则来诊断。注意是诊断而不应将它做为可以任意喷洒的香水。

    8:本模式的好处就是把方法提高类的好处,虽然有人抨击说 这不是OO 这是贫血的类。如果我们顽固的这样认为

         未免太教条了吧。

实际中的应用:

      同样在ACE中,也充分应用了本模式,它在实现主动对象模式时,用到方法对象(方法提到类的层次 还记的吗?)它继承于ACE_Method_Object 类。我们说过 “何时执行”这个逻辑是放在请求者(Invoker)角色里面的,在ACE里 所有的方法对象都被客户(client角色)实例化 并放在启用队列(activation queue)中,ACE_Task类对将该方法对象从队列取出,并调用它的call()方法。 呵呵 ACE_Task类是不是相当于请求者(Invoker)角色 它决定了“何时执行”。由于ACE_Method_Object 类是个接口类,因此 你可以 自己实现 call()方法。 这里是不是很灵活的应用了command 模式? 你可以把  ACE_Method_Object 类当作command 角色 或者 执行者角色 看你怎么认为了 !

部分代码如下:

typedef ACE_Method_Request  ACE_Method_Object;

》》 这一句你看到了吗?

class ACE_Export ACE_Method_Request
{
public:
  /// Constructor.
  ACE_Method_Request (unsigned long priority = 0);

  /// Destructor.
  virtual ~ACE_Method_Request (void);

  // = Accessors.
  /// Get priority.
  unsigned long priority (void) const;

  /// Set priority.
  /**
   * Priority values are user-defined. The default (set in the constructor)
   * is 0. The priority value is used in the ACE_Activation_Queue::enqueue()
   * method to order the method requests in the queue by priority.
   * 0 is the lowest priority.
   *
   * @param prio   unsigned long, the new priority value for this object.
   *
   * @sa ACE_Activation_Queue::enqueue
   */
  void priority (unsigned long prio);

  // = Invocation method (must be overridden by subclasses).
  /// Invoked by the scheduler to execute the request.
  /**
   * This method must be implemented by the subclass to perform the
   * desired actions.
   *
   * @return int; not interpreted by ACE. The scheduler class must
   *         decide the meaning of this return value and act on it
   *         if needed.
   */
  virtual int call (void) = 0;
private:
  /// Disallow copying and assignment.
  ACE_Method_Request (const ACE_Method_Request &);
  void operator= (const ACE_Method_Request &);
protected:
  /// The priority of the request.
  unsigned long priority_;
};


   

转载于:https://www.cnblogs.com/wangok/archive/2008/12/27/1363575.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值