设计模式之命令模式

10/24/2012 8:42:06 AM

 名称:命令模式

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

 适用环境:

 1、抽象出待执行的动作以参数化某对象。你可用过程语言中的回调函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。Command模式是回调机制的一个面向对象的替代品。

 2、在不同的时刻指定、排列和执行请求。一个Command对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求 的命令对象送给另一个不同的进程并在那儿实现该请求。

 3、支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在Command接口中添加装 载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用Excute操作重新执行它们。

4、用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务的信息系统中

常见。一个事务封装了对数据的一组变动。模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以护展系统。

    abstractclassCommand

    {

        publicabstractvoidExecute();

        publicabstractvoidUnExecute();

    }

    classCalculatorCommand: Command

    {

        privatechar_operator;

        privateint_operand;

        privateCalculator_calculator;

 

        publicCalculatorCommand(Calculatorcalculator,

            char@operator, intoperand)

        {

            this._calculator = calculator;

            this._operator = @operator;

            this._operand = operand;

        }

 

        publiccharOperator

        {

            set{ _operator = value; }

        }

 

        publicintOperand

        {

            set{ _operand = value; }

        }

 

        publicoverridevoidExecute()

        {

            _calculator.Operation(_operator, _operand);

        }

 

        publicoverridevoidUnExecute()

        {

            _calculator.Operation(Undo(_operator), _operand);

        }

        publiccharUndo(char@operator)

        {

            switch(@operator)

            {

                case'+': return'-';

                case'-': return'+';

                case'*': return'/';

                case'/': return'*';

                default:thrownew

                    ArgumentException("@operator");

            }

        }

    }

    classCalculator

    {

        privateint_curr = 0;

        publicvoidOperation(char@operator, intoperand)

        {

            switch(@operator)

            {

                case'+': _curr += operand; break;

                case'-': _curr -= operand; break;

                case'*': _curr *= operand; break;

                case'/': _curr /= operand; break;

            }

            Console.WriteLine(

                "Current value={0,3} (following {1} {2})",

                _curr, @operator, operand);

        }

    }

    classUser

    {

        privateCalculator_calculator = newCalculator();

        privateList<Command> _commands = newList<Command>();

        privateint_current = 0;

 

        publicvoidRedo(intlevels)

        {

            Console.WriteLine("\n---- Redo {0} levels ", levels);

            for(inti = 0; i < levels; i++)

            {

                if(_current < _commands.Count - 1)

                {

                    Commandcommand = _commands[_current++];

                    command.Execute();

                }

            }

        }

        publicvoidUndo(intlevels)

        {

            Console.WriteLine("\n---- Undo {0} levels ", levels);

            for(inti = 0; i < levels; i++)

            {

                if(_current > 0)

                {

                    Commandcommand = _commands[--_current] asCommand;

                    command.UnExecute();

                }

            }

        }

        publicvoidCompute(char@operator, intoperand)

        {

            Commandcommand = newCalculatorCommand(

                _calculator, @operator, operand);

            command.Execute();

 

            _commands.Add(command);

            _current++;

        }

}

调用:

Useruser = newUser();

            user.Compute('+', 100);

            user.Compute('-', 50);

            user.Compute('*', 10);

            user.Compute('/', 20);

 

            user.Undo(4);

            user.Redo(3);

 

输出:

Current value=100 (following + 100)

Current value= 50 (following - 50)

Current value=500 (following * 10)

Current value= 25 (following / 20)

 

---- Undo 4 levels

Current value=500 (following * 20)

Current value= 50 (following / 10)

Current value=100 (following + 50)

Current value=  0 (following - 100)

 

---- Redo 3 levels

Current value=100 (following + 100)

Current value= 50 (following - 50)

Current value=500 (following * 10)

15、解释器模式

/* * 名称:解释器模式

     * 意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表

* 示来解释语言中的句子。

     * 适用环境:

     * 1、当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法对时,可使

* 用解释器模式。而当存在以下情况该模式效果最好:

     * 该文法法简单对于复杂文法,文法的类层变得宠大庞大而无法管理。此时语法分析程序生成

* 器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式,这样可以节省空间

* 而且还可能节省时间。

     * 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首选

* 将它们转换成另一种形式。

     * 例如,正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,

* 该模式仍是有用的。

     * */

    classContext

    {

    }

    abstractclassAbstractExpression

    {

        publicabstractvoidInterpret(Contextcontext);

    }

    classTerminalExpression:AbstractExpression

    {

        publicoverridevoidInterpret(Contextcontext)

        {

            Console.WriteLine("Called Terminal.Interpret()");

        }

    }

    classNoterminalExpression: AbstractExpression

    {

        publicoverridevoidInterpret(Contextcontext)

        {

            Console.WriteLine("Called Noterminal.Interpret()");

        }

}

调用:

Contextcontext = newContext();

            ArrayListlist = newArrayList();

 

            list.Add(newTerminalExpression());

            list.Add(newNoterminalExpression());

            list.Add(newTerminalExpression());

            list.Add(newTerminalExpression());

            foreach(AbstractExpressionexp inlist)

            {

                exp.Interpret(context);

            }

 

输出:

Called Terminal.Interpret()

Called Noterminal.Interpret()

Called Terminal.Interpret()

Called Terminal.Interpret()