六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 124|回复: 0

温故知新(10)——命令模式

[复制链接]

升级  93.33%

58

主题

58

主题

58

主题

秀才

Rank: 2

积分
190
 楼主| 发表于 2012-12-10 15:52:59 | 显示全部楼层 |阅读模式
<div id="cnblogs_post_body">概述

  虽然并不完全符合,命令模式给我的感觉有点像数据库中的中间表。中间表将两个实体表的主键作为外键,将两个实体表关联成多对多的关系。同样命令模式中命令对象就好像中间表一样,将动作的引发者和动作的执行者关联起来,引发者无需知道执行者,执行者也无需了解是谁引发了这个动作。如果仔细想想,动作的引发者和动作的执行者之间也是多对多的关系。下面是GOF给出的意图:
  
   将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
  这局意图的前半句,个人感觉有些描述得过于抽象,这里仅供参考;后半句怎说明了命令模式的的一些应用场景和用途:
  1、可以在对象关系上解耦动作的引发者和动作的执行者;
  2、可以在时间上解耦动作的引发和动作的执行;
  3、可以实现动作的“撤销”和“重做”,也可以实现“修改日志”,当系统崩溃时,这些修改可以被重做一遍。
  4、将一组动作实现为一个事物。
  实现命令模式时需要考虑的一个问题是,命令对象的“轻”或“重”,“轻”模式时,命令对象只负责将动作的引发者和动作的执行者关联起来;而“重”模式时,命令对象自身会包含处理逻辑。个人认为通常应该将命令对象实现为“轻”模式,而在一些无需动作的执行者的特殊情况下将命令对象实现为“重”模式。
  命令模式可以与组合模式结合,即用组合模式将命令对象组合成复合命令对象。
  结构

  命令模式是一种比较灵活的模式,下面是经典命令模式的类图:
  
  模式的参与者:
  1、命令接口,所有命令对象须实现此抽象——ICommand;
  2、具体的命令,命令通常包含一个动作执行者——Command;
  3、引发动作的对象,经常是UI组件或定时组件——Invoker;
  4、动作的实际执行者——Receiver;
  5、创建命令并设置接收者——Client;
  上图中,除ICommand接口以外,每个参与者都有可能存在多个。
  示例

  系统中有很多批处理的任务,比如定期数据清理与备份,定期对某些数值进行一些计算等等,这些动作通常由一个对象(比如一个定时器)来调度,不同的动作也由不同的对象去执行。这些的动作的经常会发生增减,因此让调度对象包含所有执行者的引用,直接调用的执行者的方法,是不太现实的。同样由于希望动作的触发与动作的执行,希望构成异步,因此使用命令模式,将这些动作包装成命令对象,由这些命令对象包含具体的动作执行者的做法是可行的。
  由于是一个说明性示例,所以下面的代码忽略了定时调度、多线程等具体实现。
.codearea{ color:black;  background-color:white;  line-height:18px;  border:1px solid #4f81bd;  margin:0;  width:auto !important;  width:100%;  overflow:auto;  text-align:left;  font-size:12px;  font-family: "Courier New","Consolas","Fixedsys","BitStream Vera Sans Mono", courier,monospace,serif}.codearea pre{ color:black; line-height:18px;  padding:0 0 0 12px !important; margin:0em;  background-color:#fff !important}.linewrap pre{white-space:pre-wrap;  white-space:-moz-pre-wrap;  white-space:-pre-wrap;  white-space:-o-pre-wrap;  word-wrap:break-word;  word-break:normal}.codearea pre.alt{ background-color:#f7f7ff !important}.codearea .lnum{color:#4f81bd;line-height:18px}  1、动作执行者,下面提供两个。
  计算器Calculater。
  <div class="codearea linewrap">    1:  using System;   2:      3:  namespace DesignPatterns.Command   4:  {   5:      /// <summary>   6:      /// 计算器   7:      /// </summary>   8:      public class Calculater   9:      {  10:          public void Calculate()  11:          {  12:              Console.WriteLine("计算操作");  13:          }  14:      }  15:  }  16:
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表