1 GOF中的定义
1.1 意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作
1.2
结构图
2 初步理解方法调用
代码:
View Code
public class ClassA { public int Compute() { Calc c = new Calc(); return c.Execute(); } } public class Calc { public int Execute() { return 3; } }
说明:
类ClassA中的直接调用Calc类的Add方法,Class是方法的调用者,Calc是方法的执行者。这样的代码我们每天都在写,没有什么问题。但是当我们遇到这样的需求“对请求排队或记录请求日志,以及支持可撤消的操作”,即在调用某个方法是对方法进行排队调用。因为方法是没有类型的,而要达到对请求排队,就需要让方法先具有类型,即将行为抽象。
3 重构2中的代码
代码:
View Code
/// <summary> /// 抽象行为为接口,使方法具有类型。这样就可以在调用类ClassA中声明IList<ICommand> cmdList = new List<ICommand>(), /// 然后就可以继续实现对请的排队、记录日志、添加修改或移除请求了 /// </summary> public interface ICommand { int Execute(); } public class ConcreteCommand2 : ICommand { private int a; public int A { get { return a; } set { a = value; } } private int b; public int B { get { return b; } set { b = value; } } public int Execute() { return A-B; } } public class ConcreteCommand1 : ICommand { private int a; public int A { get { return a; } set { a = value; } } private int b; public int B { get { return b; } set { b = value; } } public int Execute() { return A+B; } } public class Invoker { private IList<ICommand> cmdList = new List<ICommand>(); public void AddCmd(ICommand cmd) { cmdList.Add(cmd); } public void Compute() { foreach (ICommand cmd in cmdList) { Console.WriteLine(cmd.Execute()); } } } static void Main(string[] args) { Invoker invoker = new Invoker(); ConcreteCommand1 cmd1 = new ConcreteCommand1(); cmd1.A = 10; cmd1.B = 10; invoker.AddCmd(cmd1); ConcreteCommand2 cmd2 = new ConcreteCommand2(); cmd2.A = 20; cmd2.B = 20; invoker.AddCmd(cmd2); invoker.Compute(); }
结构图:
说明:
代码写到这已经做到了GOF中的要求,但现在与GOF中的类图还有很大的区别。这只是应用场景的不同,因为具体实现的命令的方法,已在其它类中实现了。
4 重构3中的代码
代码:
View Code
/// <summary> /// 抽象行为为接口,使方法具有类型。这样就可以在调用类ClassA中声明IList<ICommand> cmdList = new List<ICommand>(), /// 然后就可以继续实现对请的排队、记录日志、添加修改或移除请求了 /// </summary> public interface ICommand { int Execute(); } public class ConcreteCommand1 : ICommand { private Receiver1 receiver; public ConcreteCommand1(Receiver1 receiver) { this.receiver = receiver; } public int Execute() { return receiver.Sub(); } } public class ConcreteCommand2 : ICommand { private Receiver2 receiver; public ConcreteCommand2(Receiver2 receiver) { this.receiver = receiver; } public int Execute() { return receiver.Add(); } } public class Receiver1 { private int a; public int A { get { return a; } set { a = value; } } private int b; public int B { get { return b; } set { b = value; } } public int Sub() { return A - B; } } public class Receiver2 { private int a; public int A { get { return a; } set { a = value; } } private int b; public int B { get { return b; } set { b = value; } } public int Add() { return A + B; } } public class Invoker { private IList<ICommand> cmdList = new List<ICommand>(); public void AddCmd(ICommand cmd) { cmdList.Add(cmd); } public void Compute() { foreach (ICommand cmd in cmdList) { Console.WriteLine(cmd.Execute()); } } } static void Main(string[] args) { Invoker invoker = new Invoker(); Receiver1 rec1 = new Receiver1(); rec1.A = 10; rec1.B = 10; ConcreteCommand1 cmd1 = new ConcreteCommand1(rec1); invoker.AddCmd(cmd1); Receiver2 rec2 = new Receiver2(); rec2.A = 20; rec2.B = 20; ConcreteCommand2 cmd2 = new ConcreteCommand2(rec2); invoker.AddCmd(cmd2); invoker.Compute(); }
结构图:
说明:
加了一个Receiver类(已具体实现了某个方法的类)。ConreteCommand只需一个Receiver类的某个具体方法,而不需要其它方法,在图2中加入适配器模式。