7. 命令模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/llz62378/article/details/78168933

        这个模式的深入的了解下来内容还是很多的。文中使用遥控器的例子,对此模式的各种用法进行了详细介绍。总结出以下几点内容: 

1. 各种命令


1.1 开关一个设备execute

一个遥控器中有多个按钮,可以控制多个设备的开关。

class RemoteControl
{
public:
     RemoteControl();
     void SetCommand(int idx, Command *onCmd, Command *offCmd)
     void OnButtonWasPushed(int idx)
     void OffButtonWasPushed(int idx)
     void Undo(int idx);
private:
     Command *onCmd;
     Command *offCmd;
     Command *undoCmd;
};

RemoteControl::RemoteControl()
{
     onCmd = new Command[7];
     offCmd = new Command[7];
     
     Command *noCmd = new NoCmd(); //空对象, 好处在执行时不需要判断cmd是否为null.
     for(int i =0; i<7; ++i)
     {
          onCmd[i] = noCmd;
          offCmd[i] = noCmd;
     }
     
     undoCmd = noCmd;
}

void RemoteControl::SetCommand(int idx, Command *onCmd, Command *offCmd)
{
     onCmd[idx] = onCmd;
     offCmd[idx] = offCmd;
}

void RemoteControl::OnButtonWasPushed(int idx)
{
     onCmd[idx].execute();
}

void RemoteControl::OffButtonWasPushed(int idx)
{
     offCmd[idx].execute();
}

LightOnCmd::LightOnCmd(Light *light)
{     
     this->light = light;
}

void LightOnCmd::Execute()
{
     light->On();
}

LightOffCmd::LightOffCmd(Light *light)
{
     this->light = light;
}

void LightOffCmd::Execute()
{
     light->Off();
}
client:
RemoteControl *remoteControl = new RemoteControl();
Light *light = new Light();
LightOnCmd *lightOnCmd = new LightOnCmd(light);
LightOffCmd *lightOffCmd = new LightOffCmd(light);

remoteControl->SetCommand(0, lightOnCmd, lightOffCmd);
remoteControl->OnButtonWasPushed(0);    // 开灯
remoteControl->OffButtonWasPushed(0);    // 关灯

1.2 撤销命令undo

1.2.1 撤销一个命令

void RemoteControl::OnButtonWasPushed(int idx)
{
     onCmd[idx].execute();
     undoCmd = onCmd[idx];
}

void RemoteControl::OffButtonWasPushed(int idx)
{
     offCmd[idx].execute();
     undoCmd = offCmd[idx]; 
}

void RemoteControl::UndoButtonWasPushed()
{
     undoCmd->Undo();
}

(1)两个状态的情况,eg. light 

void LightOnCmd::Execute()
{
     light->On();
}

void LightOnCmd::Undo()
{
     light->Off();
}

void LightOffCmd::Execute()
{
     light->Off();
}

void LightOffCmd::Undo()
{
     light->On();
}

(2)三个状态的情况,eg. fan 

int Fan::GetState()
{
     return undoState;
}

void FanHighCmd::Execute()
{
     undoState = fan->GetState();
     fan->High();    
}

void FanMidCmd::Execute()
{
     undoState = fan->GetState();
     fan->Mid();
}

void FanLowCmd::Execute()
{
     undoState = fan->GetState();
     fan->Low();
}

void FanLowCmd::Undo()
{
     if(undoState == HIGH)
          fan->High();
     else if(undoState == MID)
          fan->Mid();
     else if(undoState == LOW)
          fan->Low();   
     else if(undoState == OFF)
          fan->Off();
     else
          fan->On();
}
client:
remoteControl->UndoButtonWasPushed()

1.2.2 撤销多个命令 

在RemoteControl中添加stack<Command *> undoCmd;记录命令。先从stack取栈顶的cmd对象,再执行它的undo命令。

2. party模式 

void MacroCommand::MacroCommand(Command *cmds[])
{
     this->cmds = cmds;
}

void MacroCommand::Execute()
{
     for(auto i:cmds)
          i->Execute();
}
client:
// 1. 创建设备
Light *light = new Light();
TV *tv = new TV();
Stereo *stereo = new Stereo();

// 2. 创建对设备的操作
LightOnCmd *lightOnCmd = new LightOnCmd(light);
TVOnCmd *tvOnCmd = new TVOnCmd(tv);
StereoOnCmd *stereoOnCmd = new StereoOnCmd(stereo);

LightOffCmd *lightOffCmd = new LightOffCmd(light);
TVOffCmd *tvOffCmd = new TVOffCmd(tv);
StereoOffCmd *stereoOffCmd = new StereoOffCmd(stereo);

// 3. 将一起执行的命令放在命令集中
Command *partyOn[3] = {lightOnCmd,tvOnCmd,stereoOnCmd};
Command *partyOff[3] = {lightOffCmd,tvOffCmd,stereoOffCmd};

// 4. 创建多命令一起操作的对象
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);

// 5. 注册命令:将多命令放入遥控器中
remoteCommand.setCommand(0, partyOnMacro, partyOffMacro);

//6.执行命令
remoteCommand.OnButtonWasPushed(0);
remoteCommand.OffButtonWasPushed(0);

 3.  两个应用


3.1 工作队列

      将一个个命令放入到工作队列中,之后由线程从队列中取命令,执行相应命令的execute()进行处理。

3.2 数据库操作的redo

      由于系统可能宕机,需要在宕机后恢复到之前的状态。所以在执行每个命令时会将命令存储在磁盘(记录日志)中,在做恢复时重新加载这些对象,并按顺序执行。








猜你喜欢

转载自blog.csdn.net/llz62378/article/details/78168933