命令模式 Command Pattern

命令模式 Command Pattern

1.定義

命令模式將“請求”封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其他對象,同時支持可撤消的操作。

2.目的:

命令模式是爲了解決命令的請求者和命令的實現者之間的耦合關係。
+ 方便對命令的擴展。
+ 可以對多個命令進行統一的控制。

3.模式解析

圖示:
這裏寫圖片描述

經典命令模式包含4個角色:

  • 命令(Command)角色:定義命令的統一接口,這是一個抽象角色。
  • 具體命令(ConcreteCommand)角色:Command接口的實現者,用來執行具體的命令,實現Execute()方法,某些情況下可以直接用來充當Receiver。
  • 接收者(Receiver)角色:命令的實際執行者。
  • 請求者(Invoker)角色:命令的請求者,命令模式中最重要的角色。這個角色用來對各個命令進行控制。

4.總結:

命令模式很適合實現諸如撤消,重做,回放,時間倒流之類的功能

5.代碼實例:

#pragma once
#include <iostream>
using namespace std;
#include <list>

//命令的實際執行者
class Calculator
{
public:
    Calculator():_curr(0){}

    void Operation( char _operator , int operand)
    {
        switch (_operator)
        {
        case '+' : _curr += operand ; break;
        case '-' : _curr -= operand ; break;
        case '*' : _curr *= operand ; break;
        case '/' : _curr /= operand ; break;
        }
        cout<<"Current value = "<<_curr<<" ( following " <<_operator << operand  << " )" <<endl;
    }

private:
    int _curr ;
};


//定義命令的統一接口
class  Command
{
public:
    virtual void Execute()   = 0;
    virtual void UnExecute() = 0;
};

//Command接口的實現者,用來執行具體的命令
class CalculatorCommand : public Command
{
public:
    CalculatorCommand( Calculator* calculator , char t_operator  , int operand )
    {
        _operator   = t_operator;
        _calculator = calculator;
        _operand    = operand;
    }

    char SetOperator( char  value )
    {
        _operator = value;
    }
    int SetOperand( int value )
    {
        _operand = value;
    }

    void Execute() 
    {
        _calculator->Operation(_operator , _operand );
    }

    void UnExecute()
    {
        _calculator->Operation( Undo(_operator),_operand );
    }

    char  Undo( char t_operator )
    {
        switch (_operator)
        {
        case '+' : return '-';
        case '-' : return '+';
        case '*' : return '/';
        case '/' : return '*';
        }
    }

private:
    char _operator;
    int  _operand;
    Calculator*   _calculator;
};

//命令的請求者
class User
{
public:

    User():_current(0)
    {
        _calculator = new Calculator();
    }
    void Compute(  char t_operator  , int operand )
    {
        Command * command = new CalculatorCommand( _calculator , t_operator ,operand );
        command->Execute();

        _commands.push_back( command );
        _current++ ;
    }

    void Undo( int levels )
    {
        cout<<"------ Undo "<<levels<<" levels"<<endl;
        for( int i = 0; i < levels ; i++ )
        {
            if(  _current >  0 )
            {
                int num = 0;
                list<Command*>::iterator it = _commands.begin();
                for( ; it != _commands.end() ;it++)
                {
                    num++;
                    if( num == _current )
                    {
                        Command* com = *it;
                        com->UnExecute();
                        _current--;
                    }
                }
            }
        }
    }

    void Redo( int levels )
    {
        cout<<"------ Redo "<<levels<<" levels"<<endl;
        for( int i = 0 ; i < levels ; i++ )
        {
            if( _current < _commands.size() - 1 )
            {
                int num = 0;
                list<Command*>::iterator it = _commands.begin();
                for( ; it != _commands.end() ;it++)
                {                   
                    if( num == _current )
                    {
                        Command* com = *it;
                        com->Execute();
                        _current++;
                    }
                    num++;
                }
            }
        }
    }

private:
    Calculator*     _calculator;
    list<Command*>  _commands;
    int             _current ;
};

class CommandExample1
{
public:
    CommandExample1(void);
    ~CommandExample1(void);

    void Start()
    {
        User* user = new User();
        user->Compute('+' , 100);
        user->Compute('-' , 50);
        user->Compute('*' , 10);
        user->Compute('/' , 2);

        user->Undo(4);

        user->Redo(3);
    }
};

實驗結果

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章