h3>Gof定义

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

动机

在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比如需
要对行为进行“记录、撤销/重做(undo/redo)、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

先来看个反例(版本1),假设在一个应用程序中需要用到要用到很多的一些外部的类,并且要对这些类中的操作进行撤销、记录等操作,如果像下面这样实现就会很乱并且不容易实现:

public class Application
{public void Process(){Document doc = new Document();doc.ShowText();Graphics gra = new Graphics();gra.Draw();//需要进行undo 记录等操作}
}
public class Document
{public void ShowText() { }
}
public class Graphics
{public void Draw(){ }
}

要满足上面提的那些要求就需要用命令模式,命令模式结构图如下:

改进后的代码(版本2),将ShowText Draw这种行为抽象起来放到一个接口中,接口命名为ICommand,并且在该接口中还有一个方法签名Undo,用来做撤销处理,当然根据需要还可以加其他的操作。ICommand代码如下:

public interface ICommand
{void Execute();void Undo();
}

Document类和Graphics类实现该接口,并提供自己的实现,代码如下:

public class Document:ICommand
{public string Name { get;set;}public Document(string name){Name = name;}public void Execute(){Console.WriteLine("显示文本 "+Name);}public void Undo(){Console.WriteLine("撤销显示文本 "+Name);}
}public class Graphics : ICommand
{public string Name { get;set;}public Graphics(string name){Name = name;}public void Execute(){Console.WriteLine("画图 "+Name);}public void Undo(){Console.WriteLine("撤销画图 "+Name);}
}

客户端调用的代码:

public class Application
{public Stack<ICommand> stack=new Stack<ICommand>();public void Show(){foreach (ICommand cmd in stack){cmd.Execute();}}public void Undo(){ICommand command = stack.Pop();command.Undo();}
}

static void Main(string[] args)
{Application app = new Application();app.stack.Push(new Document("1"));app.stack.Push(new Graphics("1"));app.stack.Push(new Document("2"));app.stack.Push(new Graphics("2"));app.Show();app.Undo();Console.ReadLine();
}

上面的代码运行结果如下:

从结果中可以看出,最后执行的画图2 被撤销了。

在上面的代码中,像Document、Graphics这样的类都是实现了ICommand接口,如果项目中已经存在这样的类然后还要将这些类去实现ICommand接口,显然不是很合理,那么就需要添加DocumentCommand类来进行转化。完整代码如下(版本3):

public class Document
{public void ShowText(){Console.WriteLine("显示文本 ");}
}
public class Graphics
{public void Draw(){Console.WriteLine("画图 ");}
}
public interface ICommand
{void Execute();void Undo();
}
/// <summary>
/// 具体化的文档命令类
/// </summary>
public class DocumentCommand : ICommand
{Document _doc;public DocumentCommand(Document doc){_doc = doc;}public void Execute(){_doc.ShowText();}public void Undo(){Console.WriteLine("撤销显示文本 ");}
}
/// <summary>
/// 具体化的图像命令类
/// </summary>
public class GraphicsCommand : ICommand
{Graphics _gra;public GraphicsCommand(Graphics gra){_gra = gra;}public void Execute(){_gra.Draw();}public void Undo(){Console.WriteLine("撤销画图 ");}
}
public class Application
{public Stack<ICommand> stack = new Stack<ICommand>();public void Show(){foreach (ICommand cmd in stack){cmd.Execute();}}public void Undo(){ICommand command = stack.Pop();command.Undo();}
}
class Program
{static void Main(string[] args){Application app = new Application();app.stack.Push(new DocumentCommand(new Document()));app.stack.Push(new GraphicsCommand(new Graphics()));app.Show();app.Undo();Console.ReadLine();}
}

在版本1中Application类中直接和Document中的方法相耦合,进过一步步改进后,Application类只和Document和Graphics的抽象耦合,达到了解耦的目的。

Command模式的几个要点

  • Command模式的根本目的在于将“行为请求者”与“行为实现者” 解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。
  • 实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。
  • 通过使用Composite模式,可以将多个“命令”封装为一个“复合命令”MacroCommand。
  • Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”来定义行为接口规范,更严格,更符合抽象原则;Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱。

返回开篇(索引)

转载于:https://www.cnblogs.com/oec2003/archive/2009/12/30/1636406.html

设计模式笔记(15)---命令模式(行为型)相关推荐

  1. 设计模式笔记:命令模式

    首先看看命令模式的定义:命令模式将请求封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持撤销的操作. 所谓参数化,我的理解是实际执行的对象,比如light(电灯).strer ...

  2. Head First 设计模式笔记 5.命令模式

    文章目录 设计要求 命令模式 实际实现 命令模式具体应用 设计要求 小明接到了新任务,要求设计一个遥控器,这个遥控器上面有七个插槽,每个插槽都有对应的开和关按钮.要求每个都能控制任意家电如灯,电视,电 ...

  3. 【白话设计模式八】命令模式(Command)

    为什么80%的码农都做不了架构师?>>>    #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...

  4. Head First 设计模式中的命令模式 的一个错误

    最近在看Head First 设计模式,其中命令模式中有讲到实现撤销功能,并且作者还出了一道题, 下面的是书中习题: public class MarcoCommand implements Comm ...

  5. 设计模式之命令模式(行为型)

    目录 一.模式定义 二.模式角色 三.模式分析 四.典型例子 五.适用场景 一.模式定义 命令模式(Command Pattern):将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分离,两 ...

  6. 【转】设计模式学习笔记之命令模式

    定义:将请求封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式支持可撤销等操作. 命令模式将发出请求的对象和执行请求的对象解耦.在被解耦的两者之间是通过命令对象进行沟通的. 案例代 ...

  7. 【学习笔记】命令模式与备忘录之简单计算器

    挺长时间没写博文了,发现如果要写一篇(个人感觉上的)比较完整的博文,还是需要花费挺长的时间的,前阵子忙着一些资料复习,没能动手写笔记心得与实验.虽然写文章挺耗费时间的, 但是所能得到的也很多,在写的过 ...

  8. 《Head First 设计模式》之命令模式——遥控器

    命令模式(Command) --将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 要点 将发出请求的对象和执行请求的对象解耦. ...

  9. 我学的是设计模式的视频教程——命令模式vs策略模式,唠嗑

    课程视频 命令模式vs策略模式 唠嗑 课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 版权声明:本文博主原创文章,博客,未经同意不得转载.

最新文章

  1. js中将 整数转成字符,,将unicode 编码后的字符还原出来的方法。
  2. linux上利用crontab定时备份postgres数据库及文件到windows系统
  3. Skipping failed optional dependency /chokidar/fsevents
  4. Cadence Virtuoso IC617的启动和新建工程
  5. linux下iptables的编译及简单使用
  6. 【C、C++】ctype.h、cctype中的isnumber()函数和isdigit()函数的区别
  7. 2015 ACM Syrian Collegiate Programming Contest
  8. 企业搭建网站主要流程以及六个基本步骤
  9. 汇编指令——bic(位清除)、orr(位或)、eor (异或)
  10. Linux 机器重启reboot命令
  11. 移动开发——Java
  12. 【学习设计模式6】单枪匹马只身一人——单例模式
  13. SpringBoot 时间格式化的 5 种实现方法,你用的是哪种?
  14. 钢铁侠--男人要对自己狠一点~~
  15. 晒晒我的厨艺修炼成果
  16. 草图大师怎么渲染全景图?Sketchup渲染全景图的操作办法和方式!
  17. Unity EvenTrigerer UI交互组件
  18. layout_marginBottom的使用(将VIEW放置在布局底部)
  19. http://www.skycn.com/soft/20700.html#download
  20. 基于华为云会议SDK 24行代码打造企业专属会议室

热门文章

  1. 推荐 | 微软SAR近邻协同过滤算法拆解(二)
  2. 聚类 | Map-Equation多级网络聚类模型——InfoMap
  3. AtomicInteger原子整形与ReentrantLock锁
  4. CentOS7.2部署KVM虚拟机
  5. laravel学习笔记------Route::resource和Form-Model-Binding
  6. GitLab容器注册服务已集成于Docker容器
  7. asp.net 百度编辑器 UEditor 上传图片 图片上传配置 编辑器配置 网络连接错误,请检查配置后重试...
  8. 在文本框的光标处插入指定的文本(兼容IE6和Firefox)
  9. 前端开发和设计必备的Chrome插件
  10. swager java_Swagger介绍及使用