十五、命令(Command)模式--行为型模式(Behavioral Pattern)
命令模式又称为行动(Action)模 式或交易(Transaction)模式。命令模式把一个请求或者操作封装到一个对象中。
命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象.
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许
请求的一方和接收的一方独立开来,使 得 请 求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
命令模式类图:

命令模式涉及到五个角色,它们分别是:
• 客户(Client)角色:创建了一个具体命令 (ConcreteCommand)对象并确定其接收者。
• 命令(Command)角色:声明了一个给所有具体命令类 的抽象接口。这是一个抽象角色。
• 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现 Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。
• 请求者(Invoker)角色:负责调用命令对象执行请求, 相关的方法叫做行动方法。
• 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
示例代码:
class Program
{
static void Main(string[] args)
{
Receiver r = new Receiver();
Command command = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(command);
i.ExecuteCommand();
Console.ReadKey();
}
} abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
} class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver)
: base(receiver)
{ }
public override void Execute()
{
receiver.Action();
}
} class Receiver
{
public void Action()
{
Console.WriteLine("Called Receiver.action()"); }
} class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
} public void ExecuteCommand()
{
command.Execute();
}
}
运行结果:

在下面的情况下应当考虑使用命令模式:
1、使用命令模式作为"CallBack"在面向对象系统中的替代。"CallBack"讲的便是先将一个函数 登记上,然后在以后调用此函数。
2、需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,
而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也 可以在网络的另外一个地址。命令对象可以在串形化之后传送到另外一台机器上去。
3、系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命 令所产生的效果时,可以调用 undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供 redo()方法,以供客户端在需要时,再重新实施命令效果。
4、如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读 回所有的数据更新命令,重新调用 Execute()方法一条一条执行这些命令,从而恢复系统在崩 溃前所做的数据更新。
5、一个系统需要支持交易(Transaction)。一个交易结构封装了一组数据更新命令。使用命令 模式来实现交易结构可以使系统增加新的交易类型。
使用命令模式的优点和缺点
命令允许请求的一方和接收请求的一方能够独立演化,从而且有以下的优点:
• 命令模式使新的命令很容易地被加入到系统里。
• 允许接收请求的一方决定是否要否决(Veto)请求。
• 能较容易地设计-个命令队列。
• 可以容易地实现对请求的Undo 和 Redo。
• 在需要的情况下,可以较容易地将命令记入日志。
• 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
• 命令类与其他任何别的类一样,可以修改和推广。
• 你可以把命令对象聚合在一起,合成为合成命令。比如宏命令便是合成命令的例子。合 成命令是合成模式的应用。
• 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
命令模式的缺点如下:
• 使用命令模式会导致某些系统有过多的具体命令类。某些系统可能需要几十个,几百个 甚至几千个具体命令类,这会使命令模式在这样的系统里变得不实际。
十五、命令(Command)模式--行为型模式(Behavioral Pattern)的更多相关文章
- FactoryMethod工厂方法模式(创建型模式)
1.工厂方法模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只 ...
- Prototype原型模式(创建型模式)
1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...
- C#设计模式之十五命令模式(Command Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第二个模式,该模式是[命令模式],又称为行动(Action)模式或交易(Transaction)模式,英文名称是:Command P ...
- 设计模式(十四):Command命令模式 -- 行为型模式
1.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...
- 设计模式学习之命令模式(Command,行为型模式)(12)
一.命令模式的定义 命令模式属于对象的行为型模式.命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开.命令模式的实现可以提供命令的撤销和恢复功能 ...
- 设计模式(五):PROTOTYPE原型模式 -- 创建型模式
1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...
- 悟空模式-java-原型模式
[却说那妖精与大圣斗经半日,不分胜败.行者把棒丢起,叫一声“变!”就以一变十,以十变百,以百变千,半天里,好似蛇游蟒搅,乱打妖邪.妖邪慌了手脚,将身一闪,化道清风,即奔碧空之上逃走.行者念声咒语,将铁 ...
- 工厂方法模式——创建型模式02
1. 简单工厂模式 在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...
- 建造者模式与原型模式/builder模式与prototype模式/创建型模式
建造者模式 定义 用于简化复杂对象的创建 JDK中的建造者模式 java.lang.StringBuilder中的append()方法,每次调用后返回修改后的对象本身. public StringBu ...
- 设计模式(二): BUILDER生成器模式 -- 创建型模式
1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式 ...
随机推荐
- discuz@功能的代码
//转载 $atlist = $atlist_tmp = $ateduids = array(); preg_match_all("/@([^\r\n]*?)\s/i", $mes ...
- a:hover和a:visited书写顺序的重要性
2a:hover和a:visited书写顺序的重要性今天在用a:hover属性的时候发现一个奇怪的问题,同一个页面里面有些链接的a:hover效果不能正常表现出来.链接的代码是一样,没有使用其它样式固 ...
- BZOJ 1036 [ZJOI2008]树的统计Count(动态树)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 题意:一棵树,每个节点有一个权值.三种操作:(1)修改某个节点的权值:(2)输出某两 ...
- 【给你几个使用Xamarin的理由】
写在开篇前 这种代理操作,绑定影射的机制,有些极端的开发者确实难以接受.追求完美,总感觉原生的各种优点. 如果你非得较这个真,那您还是感觉补习下 Java Eclipse ,买一台Mac 恶补Obj ...
- SSH自动部署
我的是windows环境,目前开发的过程中,有些项目需要一下子部署到很多的linux服务器上.写了个脚本能够自动上传文件和执行部署任务.完成这个任务需要的条件包括SSH配置和一个执行脚本. 准备 1. ...
- (转)open和fopen的区别:
fopen与open的区别 open和fopen的区别: 1.缓冲文件系统缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存“缓 ...
- CentOS下安装无线网卡驱动 (转)
1. 确定自己的网卡和内核版本:lspci | grep Network #根据输出的信息确定网卡的型号.uname -a #确定内核版本 2. 配置yum使用RPMForg ...
- Factorials 阶乘
Description N的阶乘写作N!表示小于等于N的所有正整数的乘积.阶乘会很快的变大,如13!就必须用32位整数类型来存储,70!即使用浮点数也存不下了.你的任务是找到阶乘最后面的非零位.举个例 ...
- python中自定义类对象json字符串化的方法
1. 用 json 或者simplejson 就可以 2.定义转换函数: def convert_to_builtin_type(obj): print 'default(', repr(obj), ...
- 多线程下不反复读取SQL Server 表的数据
在进行一些如发送短信.邮件的业务时,我们常常会使用一个表来存储待发送的数据,由后台多个线程不断的从表中读取待发送的数据进行发送.发送完毕后再将数据转移到历史表中,这样保证待发送表的数据普通情况下不会太 ...