C#设计模式——命令模式(Command Pattern)
一、概述
通常来说,“行为请求者”与“行为实现者”是紧耦合的。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这些情况下,将“行为请求者”与“行为实现者”解耦,实现二者之间的松耦合就至关重要。命令模式是解决这类问题的一个比较好的方法。
二、命令模式
命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式的结构图如下
Command定义了命令的接口
ConcreteCommand实现Command接口,定义了具体的命令
Client用于创建具体的命令并设定接收者
Invoker要求Command执行相应的请求
Receiver实施与执行一个请求,任何一个类都可能作为Receiver。
三、示例
假定要实现一个绘图系统,要求支持撤销功能,下面就用命令模式来实现这一需求。
首先定义一个抽象的命令接口
1 publicinterface IGraphCommand
2 {
3 void Draw();
4 void Undo();
5 }
接着实现具体的绘图命令
publicclass Line : IGraphCommand
{
private Point startPoint;
private Point endPoint;
public Line(Point start, Point end)
{
startPoint = start;
endPoint = end;
}
publicvoid Draw()
{
Console.WriteLine("Draw Line:{0} To {1}", startPoint.ToString(), endPoint.ToString());
}
publicvoid Undo()
{
Console.WriteLine("Erase Line:{0} To {1}", startPoint.ToString(), endPoint.ToString());
}
}
publicclass Rectangle : IGraphCommand
{
private Point topLeftPoint;
private Point bottomRightPoint;
public Rectangle(Point topLeft, Point bottomRight)
{
topLeftPoint = topLeft;
bottomRightPoint = bottomRight;
}
publicvoid Draw()
{
Console.WriteLine("Draw Rectangle: Top Left Point {0}, Bottom Right Point {1}", topLeftPoint.ToString(), bottomRightPoint.ToString());
}
publicvoid Undo()
{
Console.WriteLine("Erase Rectangle: Top Left Point {0}, Bottom Right Point {1}", topLeftPoint.ToString(), bottomRightPoint.ToString());
}
}
publicclass Circle : IGraphCommand
{
private Point centerPoint;
privateint radius;
public Circle(Point center, int radius)
{
centerPoint = center;
this.radius = radius;
}
publicvoid Draw()
{
Console.WriteLine("Draw Circle: Center Point {0}, Radius {1}", centerPoint.ToString(), radius.ToString());
}
publicvoid Undo()
{
Console.WriteLine("Erase Circle: Center Point {0}, Radius {1}", centerPoint.ToString(), radius.ToString());
}
}
然后再定义绘图类作为命令接收者
1 publicclass Graphics
2 {
3 Stack<IGraphCommand> commands =new Stack<IGraphCommand>();
4
5 publicvoid Draw(IGraphCommand command)
6 {
7 command.Draw();
8 commands.Push(command);
9 }
10
11 publicvoid Undo()
12 {
13 IGraphCommand command = commands.Pop();
14 command.Undo();
15 }
16 }
最后看一下如何调用
1 staticvoid Main(string[] args)
2 {
3 Line line =new Line(new Point(10, 10), new Point(100, 10));
4 Rectangle rectangle =new Rectangle(new Point(20, 20), new Point(50, 30));
5 Circle circle =new Circle(new Point(500, 500), 200);
6
7 Graphics graphics =new Graphics();
8 graphics.Draw(line);
9 graphics.Draw(rectangle);
10 graphics.Undo();
11 graphics.Draw(circle);
12
13 Console.ReadLine();
14 }