Command命令模式(行为型)
作用:
命令模式分离客户端的操作请求和请求的执行者。这种模式非常有用,它支持:
1、发送请求给多个接受着
2、排队、日志、拒绝请求
3、原始、简单的操作组合成高层事务
4、重做、撤销功能
Role
The Command pattern creates distance between the client that requests an operation and the object that can perform it. This pattern is particularly versatile. It cansupport:
• Sending requests to different receivers
• Queuing, logging, and rejecting requests
• Composing higher-level transactions from primitive operations
• Redo and Undo functionality
设计:
ICommand,执行操作的接口说明
Invoker,调用命令执行操作
Command,实现了操作的类,它通过调用接受者的操作来实现接口中说明的执行操作
Receiver,任意可执行请求活动的类
Action,需要被执行的操作
举例:
ICommand,菜单项
Command,剪切项
Receiver,执行剪切操作的接受者
Invoker,点击“剪切”菜单项
Action,执行“剪切”
实现:
示例1
代码
class
Document
{
public
string
strContent;
public
Document()
{
strContent
=
""
;
}
}
abstract
class
Command
{
public
Command()
{ }
public
abstract
void
Excute();
}
//
写操作
class
WriteCommand : Command
{
Document doc;
ArrayList ObjectState;
public
WriteCommand(Document doc, ArrayList state)
{
this
.doc
=
doc;
ObjectState
=
state;
}
public
override
void
Excute()
{
doc.strContent
+=
Console.ReadLine();
ObjectState.Add(doc.strContent);
}
}
//
删除操作
class
DeleteCommand : Command
{
Document doc;
ArrayList ObjectState;
public
DeleteCommand(Document doc, ArrayList state)
{
this
.doc
=
doc;
ObjectState
=
state;
}
public
override
void
Excute()
{
doc.strContent
=
doc.strContent.Substring(
0
, doc.strContent.Length
-
1
);
ObjectState.Add(doc.strContent);
}
}
//
撤销操作
class
UnDoCommand : Command
{
Document doc;
ArrayList ObjectState;
public
UnDoCommand(Document doc, ArrayList state)
{
this
.doc
=
doc;
ObjectState
=
state;
}
public
override
void
Excute()
{
doc.strContent
=
(
string
)ObjectState[ObjectState.Count
-
2
];
ObjectState.Add(doc.strContent);
}
}
class
Program
{
static
void
Main(
string
[] args)
{
Document doc
=
new
Document();
Console.WriteLine(
"
Please Input next operation:
"
);
string
strOperation
=
Console.ReadLine();
Command com
=
null
;
ArrayList ObjectState
=
new
ArrayList();
//
Record state
while
(strOperation
!=
"
Exit
"
)
{
switch
(strOperation.ToLower())
{
case
"
write
"
:
com
=
new
WriteCommand(doc, ObjectState);
com.Excute();
Console.WriteLine(
"
Write Operation:
"
+
doc.strContent);
break
;
case
"
del
"
:
com
=
new
DeleteCommand(doc, ObjectState);
com.Excute();
Console.WriteLine(
"
Delete Operation:
"
+
doc.strContent);
break
;
case
"
undo
"
:
com
=
new
UnDoCommand(doc, ObjectState);
com.Excute();
Console.WriteLine(
"
UnDo Operation:
"
+
doc.strContent);
break
;
default
:
Console.WriteLine(
"
Wrong Operation:
"
);
break
;
}
Console.WriteLine(
"
Please Input next operation:
"
);
strOperation
=
Console.ReadLine();
}
}
}
运行结果:
Please Input next operation:
write
k
Write Operation:k
Please Input next operation:
write
i
Write Operation:ki
Please Input next operation:
write
d
Write Operation:kid
Please Input next operation:
write
d
Write Operation:kidd
Please Input next operation:
del
Delete Operation:kid
Please Input next operation:
undo
UnDo Operation:kidd
Please Input next operation:
示例2
代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
Command
{
class
Program
{
delegate
void
Invoker();
static
Invoker Execute, Undo, Redo;
class
Command
{
public
Command(Receiver receiver)
{
Execute
=
receiver.Action;
Redo
=
receiver.Action;
Undo
=
receiver.Reverse;
}
}
public
class
Receiver
{
string
build, oldbuild;
string
s
=
"
some string
"
;
public
void
Action()
{
oldbuild
=
build;
build
+=
s;
Console.WriteLine(
"
Receiver is adding
"
+
build);
}
public
void
Reverse()
{
build
=
oldbuild;
Console.WriteLine(
"
Receiver is reverting to
"
+
build);
}
}
static
void
Main(
string
[] args)
{
new
Command (
new
Receiver());
Execute();
Redo();
Undo();
Execute();
Console.ReadLine();
}
}
}
应用场景:
命令可以由不同的方式由不同的接受者执行
简单的操作实现高层命令
在不同的时候指明,排队,执行命令
需要命令支持撤销功能
支持审计、所有命令执行日志记录
Use the Command pattern when…
You have:
• Commands that different receivers can handle in different ways
• A high-level set of commands that are implemented by primitive operations
You want to:
• Specify, queue, and execute commands at different times
• Support an Undo function for commands
• Support auditing and logging of all changes via commands
总结:
Command命令模式是一种行为型模式,它主要解决的问题是:在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”的问题。GoF《设计模式》中说道:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
Command模式的几个要点:
1、 Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。
2、 实现ICommand接口的具体命令对象Command 有时候根据需要可能会保存一些额外的状态信息。
3、 Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”类定义行为接口规范,更严格,更符合抽象原则:Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱
实现Command模式需要考虑的一些问题:
1、 支持取消和重做:为了达到这个目的Command类中要存储额外的状态信息。也就是上图中Command的state属性。
2、 避免取消操作中过程中的错误积累:由于命令重复的执行、取消执行和重执行的过程可能会积累错误,以致一个应用的状态最终偏离初始值。这就有必要在Command中存入更多的信息以保证这些对象可被精确的复原。