首页 > 设计模式 > 初尝Command 模式

初尝Command 模式

在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。这就是本文要说的Command模式。

意图

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

结构图

Command结构图 初尝Command 模式

代码:

using System;
using System.Collections.Generic;

namespace Command
{
    class Program
    {
        static void Main(string[] args)
        {
            //只有计算能力
            Caculator c = new Caculator();
            //实现Undo
            CaculatorCommand cc = new CaculatorCommand(c);
            //添加了Undo的堆栈
            CaculatorInvoker cInvoker = new CaculatorInvoker(cc);
            cInvoker.Caculate('+',2);
            cInvoker.Caculate('*', 7);
            cInvoker.Caculate('-', 3);
            cInvoker.Caculate('/', 4);
            cInvoker.UnCaculate();
            cInvoker.UnCaculate();
            cInvoker.UnCaculate();
        }
    }

    interface Command {
        void SetParam(object[] objects);
        void Excute();
        void UnExcute();
    }

    class Caculator {
        private double total = 0;

        public void Compute(char @operator,double param) {
            switch (@operator) {
                case '+': total += param;  break;
                case '-': total -= param; break;
                case '*': total *= param; break;
                case '/': total /= param; break;
                default: throw new ArgumentException();
            }
            Console.WriteLine("Current value = {0,3} (following {1} {2})",total,@operator,param);
        }
    }

    class CaculatorCommand : Command {
        private Caculator caculator;
        private char @operator;
        private double param;

        public CaculatorCommand(Caculator c) {
            this.caculator = c;
        }
        public void SetParam(object[] objects) {
            this.@operator = (char)objects[0];
            this.param = (double)objects[1];
        }
        public void Excute() {
            caculator.Compute(@operator,param);
        }
        public void UnExcute() {
            caculator.Compute(this.Undo(@operator),param);
        }
        private char Undo(char @op) {
            switch (@op) {
                case '+': return '-';
                case '-': return '+';
                case '*': return '/';
                case '/':return '*';
                default: throw new ArgumentException();
            }
        }
    }

    class CaculatorInvoker {
        private Command cmd;
        private Stack paramsStack = new Stack();

        public CaculatorInvoker(Command cmd) {
            this.cmd = cmd;
        }

        public void Caculate(char @operator,double param) {
            object[] paras = new object[] { @operator,param};
            cmd.SetParam(paras);
            cmd.Excute();
            paramsStack.Push(paras);
        }

        public void UnCaculate() {
            if (paramsStack.Count < 0) return;
            object[] paras = paramsStack.Pop();
            cmd.SetParam(paras);
            cmd.UnExcute();
        }
    }
}


运行截图:

Command运行结果 初尝Command 模式

话说回来,如果只看Main 函数,感觉像用的是Decorator 模式。从这一点不难发现,模式之间由于总体原则的类似,导致他们长得都很相像。

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.