设计模式之 — Command命令模式

来源:互联网 发布:arttemplate.js 教程 编辑:程序博客网 时间:2024/05/21 10:44

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中加入适配器模式。