频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

行为型模式篇-命令模式(Command Pattern)

来源: 作者:TerryLee 出处:巧巧读书 2008-02-10 进入讨论组

讨论组http://group.qqread.com


一般情况下我们使用这个类的时候,都会这样去写:
class Program { static void Main(string[] args) { Document doc = new Document(); doc.Display(); doc.Undo(); doc.Redo(); } }

    这样的使用本来是没有任何问题的,但是我们看到在这个特定的应用中,出现了Undo/Redo的操作,这时如果行为的请求者和行为的实现者之间还是呈现这样一种紧耦合,就不太合适了。可以看到,客户程序是依赖于具体Document的命令(方法)的,引入Command模式,需要对Document中的三个命令进行抽象,这是Command模式最有意思的地方,因为在我们看来Display(),Undo(),Redo()这三个方法都应该是Document所具有的,如果单独抽象出来成一个命令对象,那就是把函数层面的功能提到了类的层面,有点功能分解的味道,我觉得这正是Command模式解决这类问题的优雅之处,先对命令对象进行抽象:

行为型模式篇-命令模式(Command Pattern)(图四)
                   图4



示意性代码:

/// <summary> /// 抽象命令 /// </summary> public abstract class DocumentCommand { Document _document; public DocumentCommand(Document doc) { this._document = doc; } /**//// <summary> /// 执行 /// </summary> public abstract void Execute(); }

其他的具体命令类都继承于该抽象类,如下:

行为型模式篇-命令模式(Command Pattern)(图五)
图5



示意性代码:

/**//// <summary> /// 显示命令 /// </summary> public class DisplayCommand : DocumentCommand { public DisplayCommand(Document doc) : base(doc) { } public override void Execute() { _document.Display(); } } /**//// <summary> /// 撤销命令 /// </summary> public class UndoCommand : DocumentCommand { public UndoCommand(Document doc) : base(doc) { } public override void Execute() { _document.Undo(); } } /**//// <summary> /// 重做命令 /// </summary> public class RedoCommand : DocumentCommand { public RedoCommand(Document doc) : base(doc) { } public override void Execute() { _document.Redo(); } }

    现在还需要一个Invoker角色的类,这其实相当于一个中间角色,前面我曾经说过,使用这样的一个中间层也是我们经常使用的手法,即把A对B的依赖转换为A对C的依赖。如下:

行为型模式篇-命令模式(Command Pattern)(图六)
图6



示意性代码:

/// <summary> /// Invoker角色 /// </summary> public class DocumentInvoker { DocumentCommand _discmd; DocumentCommand _undcmd; DocumentCommand _redcmd; public DocumentInvoker(DocumentCommand discmd,DocumentCommand undcmd,DocumentCommand redcmd) { this._discmd = discmd; this._undcmd = undcmd; this._redcmd = redcmd; } public void Display() { _discmd.Execute(); } public void Undo() { _undcmd.Execute(); } public void Redo() { _redcmd.Execute(); } }
现在再来看客户程序的调用代码:

class Program { static void Main(string[] args) { Document doc = new Document(); DocumentCommand discmd = new DisplayCommand(doc); DocumentCommand undcmd = new UndoCommand(doc); DocumentCommand redcmd = new RedoCommand(doc); DocumentInvoker invoker = new DocumentInvoker(discmd,undcmd,redcmd); invoker.Display(); invoker.Undo(); invoker.Redo(); } }

    可以看到:

1.在客户程序中,不再依赖于Document的Display(),Undo(),Redo()命令,通过Command对这些命令进行了封装,使用它的一个关键就是抽象的Command类,它定义了一个操作的接口。同时我们也可以看到,本来这三个命令仅仅是三个方法而已,但是通过Command模式却把它们提到了类的层面,这其实是违背了面向对象的原则,但它却优雅的解决了分离命令的请求者和命令的执行者的问题,在使用Command模式的时候,一定要判断好使用它的时机。

2.上面的Undo/Redo只是简单示意性的实现,如果要实现这样的效果,需要对命令对象设置一个状态,由命令对象可以把状态存储起来。

更多文章 更多内容请看Linux命令简介专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
讨论组问题推荐
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章