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