命令模式
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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 功能可以配合备忘录模式来实现。 功能可以配合备忘录模式来实现。
第三组 王洋 龚雪娇 张萌
命令模式 (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 功能可以配合备忘录模式来实现。 功能可以配合备忘录模式来实现。