命令模式

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
行为型设计模式 ——command命令模式 ——command命令模式
第三组 王洋 龚雪娇 张萌
命令模式 (Command) Command)
一.命令模式的由来 二.命令模式意图和适用性 三.命令模式结构 四. 实例说明 五.命令模式效果分析
一、命令模式的由来
Command命令模式是一种对象行为型模式,它 Command命令模式是一种对象行为型模式,它 主要解决的问题是:在软件构建过程中,“ 主要解决的问题是:在软件构建过程中,“行为 请求者” 请求者”与“行为实现者”通常呈现一种“紧耦 行为实现者”通常呈现一种“ 合”的问题。如下图:
下图给出了Editor命令与其激活者和接收者之间的关系,菜单项Editor 下图给出了Editor命令与其激活者和接收者之间的关系,菜单项Editor是模式 Editor命令与其激活者和接收者之间的关系 Editor是模式 中的命令激活者,在点击事件发生后,它将命令请求发送给EditorCommand EditorCommand命 中的命令激活者,在点击事件发生后,它将命令请求发送给EditorCommand命 令对象,EditorCommand再调用命令接收者Software的相关方法 再调用命令接收者Software的相关方法, 令对象,EditorCommand再调用命令接收者Software的相关方法,这样一来命 令的发出者与接收者之间由紧耦合变成了松耦合, 令的发出者与接收者之间由紧耦合变成了松耦合,这时如果我们想修改命令的 相关操作,就不需要更改客户端的代码了,更加有利于代码的复用和维护。 相关操作,就不需要更改客户端的代码了,更加有利于代码的复用和维护。命 令模式实现了命令的激活者(Invoker)与命令的接收者之间的解耦,体现了 令模式实现了命令的激活者(Invoker)与命令的接收者之间的解耦, 面向对象程序设计的一般思路。 面向对象程序设计的一般思路。
public void Run() { //执行Run命令 //执行 执行Run命令 Console.WriteLine("Copy finished!"); } } //抽象类MenuItem表示命令菜单,提供Clicked()接口 //抽象类 抽象类MenuItem表示命令菜单 提供Clicked()接口 表示命令菜单, public abstract class MenuItem { //定义Clicked接口 //定义 定义Clicked接口 public abstract void Clicked(); } //CommandItem类 它维护一个Command对象 //CommandItem类,它维护一个Command对象,在本例中属于 对象, Invoker的角色 Invoker的角色 public class CommandItem : MenuItem { public CommandItem(Command cmd)
public override void Execute() { //将请求发送给命令的接收者 //将请求发送给命令的接收者 software.Editor(); } private Software software; } //具体的运行命令类 //具体的运行命令类 public class RunCommand : Command { //绑定命令的接收对象 //绑定命令的接收对象 public RunCommand(Software doc) RunCommand(Software { software = doc; }
当我们必须向某对象提交请求,但并不知道关于 被请求的操作或请求的接受者的任何信息,此时 无法抵御变化的紧耦合是不合适的。例如:需要
对行为进行“记录、撤销/重做、事务” 对行为进行“记录、撤销/重做、事务”等处理。 我们所要做的是将依赖关系转化,将紧耦合变为 松耦合。则上图的形式转化为如下形式 :
由此我们知道引入命令模式的目的是解除命令发 出者和接收者之间的紧密耦合关系,使二者相对 独立,有利于程序的并行开发和代码的维护。
Receiver——命令接受者 Receiver——命令接受者 知道如何实施与执行一个请求相关的操作。 在结构图中, Command对象作为 Command对象作为 Invoker的一个属性,当点击事件发生时, Invoker的一个属性,当点击事件发生时, Invoker调用方法Invoker()将请求发送给 Invoker调用方法Invoker()将请求发送给 ConcreteCommand,再由 ConcreteCommand,再由 ConcreteCommand调用Execute()将请 ConcreteCommand调用Execute()将请 求发送给Receiver, Client负责创建所有的 求发送给Receiver, Client负责创建所有的 角色,并设定Command 角色,并设定Command 与Invoker 和 Receiver之间的绑定关系。 Receiver之间的绑定关系。
Baidu Nhomakorabea
//绑定命令与接收者 //绑定命令与接收者 Command ccmd = new EditorCommand(doc); Command pcmd = new RunCommand(doc); //绑定命令与激活者 //绑定命令与激活者 CommandItem cItem = new CommandItem(ccmd); CommandItem pItem = new CommandItem(pcmd); //激活命令 //激活命令 cItem.Clicked(); pItem.Clicked(); } 程序运行结果如下: 程序运行结果如下: Copy finished! Paste finished!
软件菜单控件的代码实例
首先定义Command抽象类 该类提供一个Execute接口 首先定义Command抽象类,该类提供一个Execute接口,由具体命令类实 抽象类, 接口, 现 public abstract class Command //抽象命令的基类 //抽象命令的基类 { public Command() { } public abstract void Execute(); //定义一个Execute()接口 //定义一个 定义一个Execute()接口 } public class EditorCommand : Command //具体的编译命令类 //具体的编译命令类 { public EditorCommand(Software doc) //绑定命令的接收对象 //绑定命令的接收对象 { software = doc; }
二.命令模式意图和适用性
意图: 将一个请求封装为一个对象,从而使你可用不同 的请求对客户进行参数化;对请求排队或记录请 求日志,以及支持可取消的操作。 适用性: 1、抽象出待执行的动作以参数化某对象 2、在不同的时刻指定、排列和执行请求 3、支持取消操作(Unexecute) 、支持取消操作(Unexecute) 4、支持修改日志 5、用构建在原语操作上的高层操作构造一个系统
{ //绑定一个具体命令 //绑定一个具体命令 command = cmd; } public override void Clicked() { //将请求发送给命令对象 //将请求发送给命令对象 command.Execute(); } private Command command; } static void Main(string[] args) { //创建命令的接收者对象 //创建命令的接收者对象 Software doc = new Software();
四. 实例说明
以一个简单的软件编辑器的设计为例,我们先来看一下没有使用命令模 以一个简单的软件编辑器的设计为例, 式的软件编辑器是如何实现的。如图所示: 式的软件编辑器是如何实现的。如图所示:
在新的结构中,每个 不直接向Software类发出消息,而是将 类发出消息, 在新的结构中,每个MenuItem不直接向 不直接向 类发出消息 请求先发送给与自己绑定在一起的命令对象, 请求先发送给与自己绑定在一起的命令对象,如EditorCommand和 和 RunCommand,再由这些具体命令调用 中的相关方法。 ,再由这些具体命令调用Software中的相关方法。这样 中的相关方法 一来,命令发送者与接收者之间的直接依赖关系, 一来,命令发送者与接收者之间的直接依赖关系,就改变为二者同时对命令 对象的依赖关系。这也正体现了面向对象程序设计中“ 对象的依赖关系。这也正体现了面向对象程序设计中“把变化的东西从稳定 的东西中抽象出来”的思想,即响应请求的操作是有可能变化的, 的东西中抽象出来”的思想,即响应请求的操作是有可能变化的,但客户端 部分的代码应该是稳定的。使用命令模式, 部分的代码应该是稳定的。使用命令模式,当Receiver发生变化时就不会 发生变化时就不会 影响到Invoker,因为与变化相关的代码被抽象到了 因为与变化相关的代码被抽象到了Command中。 影响到 因为与变化相关的代码被抽象到了 中
三.命令模式结构
命令模式结构图
Command——命令抽象类 Command——命令抽象类 声明执行操作的接口,并不执行这个接口,所 有的具体命令都继承自命令抽象类。 ConcreteCommand——具体命令类 ConcreteCommand——具体命令类 将一个接收者对象绑定于一个动作调用接收者 相应的操作,以实现Execute方法。 相应的操作,以实现Execute方法。 Client——客户端程序 Client——客户端程序 创建一个具体命令对象并设定它的接收者。 Invoker——命令激活者 Invoker——命令激活者 将命令请求传递给相应的命令对象。
public override void Execute() { //将请求发送给命令的接收者 //将请求发送给命令的接收者 software.Run(); software.Run(); } private Software software; software; } //命令的接收者Software提供Editor和Run的具体操作 //命令的接收者Software提供Editor和Run的具体操作: 命令的接收者Software提供Editor 的具体操作: public class Software { public Software () { } public void Editor() { //执行Editor命令 //执行 执行Editor命令 Console.WriteLine(" Editor finished!"); }
我们看到,命令的激活者首先发消息给具体命令, 我们看到,命令的激活者首先发消息给具体命令,再由具体 命令调用接收者的相关方法,得到了正确的输出结果。 命令调用接收者的相关方法,得到了正确的输出结果。
五.命令模式效果分析
Command模式将调用操作的对象与知道如何 Command模式将调用操作的对象与知道如何 实现该操作的对象解耦 Command是头等 的对象, Command是头等 的对象,它们可像其他的对 象一样被操纵和扩展 可将多个命令装配成一个复合命令 可以很容易的增加新的Command对象 对象, 可以很容易的增加新的Command对象,因为 这无需改变已有的类。 这无需改变已有的类。 从定义可以看出备忘录模式是专门来存放对象历 史状态的,这对于很好的实现undo、redo功能 史状态的,这对于很好的实现undo、redo功能 有很大的帮助。所以在命令模式中undo、 有很大的帮助。所以在命令模式中undo、redo 功能可以配合备忘录模式来实现。 功能可以配合备忘录模式来实现。
相关文档
最新文档