命令模式的定义

命令模式属于对象的行为型模式。命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开。命令模式的实现可以提供命令的撤销和恢复功能。

  • Receive接收者角色
          该角色就是干活的角色,命令传递到这里是应该被执行的。 
  • Command命令角色
          需要执行的所有命令都这里声明。 
  • Invoker调用这角色
          接收到命令,并执行命令。
 
具体命令模式的实现代码如下所示:
namespace ConsoleApplication1
{
/// <summary>
/// 干活者的抽象
/// </summary>
public abstract class Receiver
{
//抽象接收者,定义每个接收者都必须完成的业务
public abstract void doSomething();
}
/// <summary>
/// 具体干活的类
/// </summary>
public class ConcrateReciver1 : Receiver
{
//每个接收者都必须处理一定的业务逻辑
public override void doSomething()
{ }
}
/// <summary>
/// 具体干活的类
/// </summary>
public class ConcrateReciver2 : Receiver
{
//每个接收者都必须处理一定的业务逻辑
public override void doSomething()
{
}
}
/// <summary>
/// 命令的抽象 命令里包含干活者的对象
/// </summary>
public abstract class Command
{
//每个命令类都必须有一个执行命令的方法
public abstract void execute();
}
public class ConcreteCommand1 : Command
{
//对哪个Receiver类进行命令处理
private Receiver receiver;
//构造函数传递接收者
public ConcreteCommand1(Receiver _receiver)
{
this.receiver = _receiver;
}
//必须实现一个命令
public override void execute()
{
//业务处理
this.receiver.doSomething();
}
}
public class ConcreteCommand2 : Command
{
//对哪个Receiver类进行命令处理
private Receiver receiver;
//构造函数传递接收者
public ConcreteCommand2(Receiver _receiver)
{
this.receiver = _receiver;
}
//必须实现一个命令
public override void execute()
{
//业务处理
this.receiver.doSomething();
}
}
/// <summary>
/// 调度者的抽象,主要负责接收命令和执行命令
/// </summary>
public class Invoker
{
private Command command;
//接收命令
public Command Command
{
set { command = value; }
}
//执行命令
public void action()
{
this.command.execute();
}
}
class Program
{
static void Main(string[] args)
{
//首先声明调用者Invoker
Invoker invoker = new Invoker();
//定义接收者
Receiver receiver = new ConcrateReciver1();
//定义一个发送给接收者的命令
Command command = new ConcreteCommand1(receiver);
//把命令交个调用者去执行
invoker.Command = command;
invoker.action();
Console.ReadLine();
}
}
}

命令模式的优缺点

优点:
  • 类间解耦
          调用者角色与接收者之间没有任何依赖关系,调用者实现功能时只需要调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。 
  • 可扩展性
          Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。 
  • 命令模式结合其他模式会更优秀
          命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。
缺点:
    如果有N个命令,Command的子类就会有N个,这个类膨胀的非常大.
 

命令模式的适用场景

在下面的情况下可以考虑使用命令模式:

  1. 系统需要支持命令的撤销(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo方法吧命令所产生的效果撤销掉。命令对象还可以提供redo方法,以供客户端在需要时,再重新实现命令效果。
  2. 系统需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命周期。意思为:原来请求的发出者可能已经不存在了,而命令对象本身可能仍是活动的。这时命令的接受者可以在本地,也可以在网络的另一个地址。命令对象可以串行地传送到接受者上去。
  3. 如果一个系统要将系统中所有的数据消息更新到日志里,以便在系统崩溃时,可以根据日志里读回所有数据的更新命令,重新调用方法来一条一条地执行这些命令,从而恢复系统在崩溃前所做的数据更新。
  4. 系统需要使用命令模式作为“CallBack(回调)”在面向对象系统中的替代。Callback即是先将一个方法注册上,然后再以后调用该方法。
应用:

让我们以上面的军训的例子来实现一个命令模式,在实现之前,可以参考下命令模式的结构图来分析下实现过程。

  军训场景中,具体的命令即是学生跑1000米,这里学生是命令的接收者,教官是命令的请求者,院领导是命令的发出者,即客户端角色。要实现命令模式,则必须需要一个抽象命令角色来声明约定,这里以抽象类来来表示。命令的传达流程是:

  命令的发出者必须知道具体的命令、接受者和传达命令的请求者,对应于程序也就是在客户端角色中需要实例化三个角色的实例对象了。

  命令的请求者负责调用命令对象的方法来保证命令的执行,对应于程序也就是请求者对象需要有命令对象的成员,并在请求者对象的方法内执行命令。

  具体命令就是跑1000米,这自然属于学生的责任,所以是具体命令角色的成员方法,而抽象命令类定义这个命令的抽象接口。

  有了上面的分析之后,具体命令模式的实现代码如下所示:

  // 教官,负责调用命令对象执行请求
public class Invoke
{
public Command _command;
public Invoke(Command command)
{
this._command = command;
}
public void ExecuteCommand()
{
_command.Action();
}
}
// 命令抽象类
public abstract class Command
{
// 命令应该知道接收者是谁,所以有Receiver这个成员变量
protected Receiver _receiver;
public Command(Receiver receiver)
{
this._receiver = receiver;
}
// 命令执行方法
public abstract void Action();
}
//
public class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver)
: base(receiver)
{
}
public override void Action()
{
// 调用接收的方法,因为执行命令的是学生44
_receiver.Run1000Meters();
}
}
// 命令接收者——学生49
public class Receiver
{
public void Run1000Meters()
{
Console.WriteLine("跑1000米");
}
}

命令模式的实现要点在于把某个具体的命令抽象化为具体的命令类,并通过加入命令请求者角色来实现将命令发送者对命令执行者的依赖分割开,在上面军训的例子中,如果不使用命令模式的话,则命令的发送者将对命令接收者是强耦合的关系,实现代码如下:

    // 院领导
class Program
{
static void Main(string[] args)
{
// 初始化Receiver、Invoke和Command63
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoke i = new Invoke(c);
// 院领导发出命令68
i.ExecuteCommand();
}
}

行为型---命令模式(Command Pattern)的更多相关文章

  1. 设计模式-15命令模式(Command Pattern)

    1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...

  2. 设计模式 - 命令模式(command pattern) 多命令 具体解释

    命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...

  3. 设计模式 - 命令模式(command pattern) 具体解释

    命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...

  4. 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释

    命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...

  5. 乐在其中设计模式(C#) - 命令模式(Command Pattern)

    原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...

  6. 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释

    命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...

  7. 二十四种设计模式:命令模式(Command Pattern)

    命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...

  8. 设计模式----行为型模式之命令模式(Command Pattern)

    下面来自head first设计模式的命令模式一章节. 定义 将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图 注: 1. ...

  9. 【UE4 设计模式】命令模式 Command Pattern

    概述 描述 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务 ...

  10. 设计模式(六):控制台中的“命令模式”(Command Pattern)

    今天的博客中就来系统的整理一下“命令模式”.说到命令模式,我就想起了控制台(Console)中的命令.无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Comm ...

随机推荐

  1. 针对zstack虚拟机导出的问题的解决办法!

    1. nfs 首先定位image所在位置: 云主机--〉云盘操作--〉配置信息--〉更多信息--安装路径 /opt/zstack/nfsprimarystorage/prim-aab63dc6284f ...

  2. linux vi如何保存编辑的文件

    按ESC键回到命令模式,输入:w保存即可,或者输入:wq!保存文件并退出. 以下是保存命令: :w   保存文件但不退出vi . :w file 将修改另外保存到file中,不退出vi . :w!   ...

  3. Python学习笔记-基础1

    一 初识Python python是一种面向对象.解释型的计算机程序语言.Python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特 ...

  4. ImportError: No module named MySQLdb</module>

    1,遇到说是没有安装某个模块的时候,第一种方法是在官网自己手动下载这个包然后安装 链接:https://pypi.org/project/MySQL-python/ 2,参考https://www.j ...

  5. 201671010147 2017年8月27号 初学java的感想

    在IT行业中,java无疑是最热门的,很多企业也青睐java,因为他的扩展性好,可以处理更多客户的数据,正是因为java有前景所以才吸引更多人去学习.在大一我们已经接触vhleC语言,大二开始就解除了 ...

  6. 《JavaScript》高级程序设计第21章:Ajax和Comet,jsonp

    一.创建XMLHttpRequest对象 二.XHR的用法 五.跨域资源共享 六.其他跨域技术七.安全七.安全 1. 图像Ping 2. JSONP(JSON with padding,填充式JSON ...

  7. 大叔学ML第一:梯度下降

    目录 原理 实践一:求\(y = x^2 - 4x + 1\)的最小值 实践二:求\(z = x^2 + y^2 + 5\)的最小值 问答时间 原理 梯度下降是一个很常见的通过迭代求解函数极值的方法, ...

  8. netty入门(一)

    1. netty入门(一) 1.1. 传统socket编程 在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费. 需要为每个线程的调用栈都分配内存,其默认值 ...

  9. CMake设置编译参数

    项目中的CMake编译参数一直参照Muduo进行设置. Muduo的CMakeLists.txt中,MAKE_CXX_FLAGS设置较为清晰明了,因此一直在项目中沿用. set(CXX_FLAGS - ...

  10. yarn组件通信协议简介

    ResourceManager与NodeManager通过ResourceTracker协议通信. NodeManager通过NodeStatusUpdaterImpl中的ResourceTracke ...