• Command命令模式


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

  • 相关阅读:
    oracle 12c迁移数据及遇到的问题
    用最有效率的方法计算 2 乘以 8?
    Java 中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
    是否可以在 static 环境中访问非 static 变量?
    什么是值传递和引用传递?
    Java 支持的数据类型有哪些?
    JDK、JRE、JVM 分别是什么关系?
    idea设置方法注释
    Java中&和&&的区别
    int和Integer有什么区别?
  • 原文地址:https://www.cnblogs.com/dataadapter/p/2650237.html
Copyright © 2020-2023  润新知