目录
[命令模式(Command Pattern)](#命令模式(Command Pattern))
命令模式(Command Pattern)
命令模式是一种行为型设计模式,它将一个请求封装成一个对象,从而使您可以用不同的请求对客户端进行参数化、对请求排队或记录请求日志,以及支持可撤销的操作。命令模式将请求的发出者和执行者解耦,使得请求的发送者无需知道执行请求的具体操作。
实际应用
家庭自动化系统
命令模式来实现控制各种设备(如灯、电视、空调)。
cpp
#include <iostream>
#include <memory>
#include <vector>
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// 接收者:灯
class Light {
public:
void on() {
std::cout << "Light is ON\n";
}
void off() {
std::cout << "Light is OFF\n";
}
};
// 接收者:电视
class TV {
public:
void on() {
std::cout << "TV is ON\n";
}
void off() {
std::cout << "TV is OFF\n";
}
};
// 接收者:空调
class AirConditioner {
public:
void on() {
std::cout << "AirConditioner is ON\n";
}
void off() {
std::cout << "AirConditioner is OFF\n";
}
};
// 具体命令:打开灯
class LightOnCommand : public Command {
private:
Light& light;
public:
LightOnCommand(Light& light) : light(light) {}
void execute() override {
light.on();
}
};
// 具体命令:关闭灯
class LightOffCommand : public Command {
private:
Light& light;
public:
LightOffCommand(Light& light) : light(light) {}
void execute() override {
light.off();
}
};
// 具体命令:打开电视
class TVOnCommand : public Command {
private:
TV& tv;
public:
TVOnCommand(TV& tv) : tv(tv) {}
void execute() override {
tv.on();
}
};
// 具体命令:关闭电视
class TVOffCommand : public Command {
private:
TV& tv;
public:
TVOffCommand(TV& tv) : tv(tv) {}
void execute() override {
tv.off();
}
};
// 具体命令:打开空调
class AirConditionerOnCommand : public Command {
private:
AirConditioner& airConditioner;
public:
AirConditionerOnCommand(AirConditioner& airConditioner) : airConditioner(airConditioner) {}
void execute() override {
airConditioner.on();
}
};
// 具体命令:关闭空调
class AirConditionerOffCommand : public Command {
private:
AirConditioner& airConditioner;
public:
AirConditionerOffCommand(AirConditioner& airConditioner) : airConditioner(airConditioner) {}
void execute() override {
airConditioner.off();
}
};
// 遥控器
class RemoteControl {
private:
std::vector<std::shared_ptr<Command>> onCommands;
std::vector<std::shared_ptr<Command>> offCommands;
public:
void setCommand(size_t slot, std::shared_ptr<Command> onCommand, std::shared_ptr<Command> offCommand) {
if (slot >= onCommands.size()) {
onCommands.resize(slot + 1);
offCommands.resize(slot + 1);
}
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
void onButtonPressed(size_t slot) {
if (slot < onCommands.size() && onCommands[slot]) {
onCommands[slot]->execute();
}
}
void offButtonPressed(size_t slot) {
if (slot < offCommands.size() && offCommands[slot]) {
offCommands[slot]->execute();
}
}
};
int main() {
Light livingRoomLight;
TV livingRoomTV;
AirConditioner livingRoomAC;
auto livingRoomLightOn = std::make_shared<LightOnCommand>(livingRoomLight);
auto livingRoomLightOff = std::make_shared<LightOffCommand>(livingRoomLight);
auto livingRoomTVOn = std::make_shared<TVOnCommand>(livingRoomTV);
auto livingRoomTVOff = std::make_shared<TVOffCommand>(livingRoomTV);
auto livingRoomACOn = std::make_shared<AirConditionerOnCommand>(livingRoomAC);
auto livingRoomACOff = std::make_shared<AirConditionerOffCommand>(livingRoomAC);
RemoteControl remote;
remote.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remote.setCommand(1, livingRoomTVOn, livingRoomTVOff);
remote.setCommand(2, livingRoomACOn, livingRoomACOff);
remote.onButtonPressed(0);
remote.offButtonPressed(0);
remote.onButtonPressed(1);
remote.offButtonPressed(1);
remote.onButtonPressed(2);
remote.offButtonPressed(2);
return 0;
}
文件操作系统
用命令模式来执行一系列文件操作(如创建、删除、重命名文件)。
cpp
#include <iostream>
#include <stack>
#include <memory>
#include <string>
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
};
// 接收者:文件系统
class FileSystem {
public:
void createFile(const std::string& filename) {
std::cout << "File created: " << filename << "\n";
}
void deleteFile(const std::string& filename) {
std::cout << "File deleted: " << filename << "\n";
}
void renameFile(const std::string& oldName, const std::string& newName) {
std::cout << "File renamed from " << oldName << " to " << newName << "\n";
}
};
// 具体命令:创建文件
class CreateFileCommand : public Command {
private:
FileSystem& fileSystem;
std::string filename;
public:
CreateFileCommand(FileSystem& fs, const std::string& filename) : fileSystem(fs), filename(filename) {}
void execute() override {
fileSystem.createFile(filename);
}
void undo() override {
fileSystem.deleteFile(filename);
}
};
// 具体命令:删除文件
class DeleteFileCommand : public Command {
private:
FileSystem& fileSystem;
std::string filename;
public:
DeleteFileCommand(FileSystem& fs, const std::string& filename) : fileSystem(fs), filename(filename) {}
void execute() override {
fileSystem.deleteFile(filename);
}
void undo() override {
fileSystem.createFile(filename);
}
};
// 具体命令:重命名文件
class RenameFileCommand : public Command {
private:
FileSystem& fileSystem;
std::string oldName;
std::string newName;
public:
RenameFileCommand(FileSystem& fs, const std::string& oldName, const std::string& newName)
: fileSystem(fs), oldName(oldName), newName(newName) {}
void execute() override {
fileSystem.renameFile(oldName, newName);
}
void undo() override {
fileSystem.renameFile(newName, oldName);
}
};
// 命令管理器
class CommandManager {
private:
std::stack<std::shared_ptr<Command>> commandStack;
std::stack<std::shared_ptr<Command>> redoStack;
public:
void executeCommand(std::shared_ptr<Command> command) {
command->execute();
commandStack.push(command);
while (!redoStack.empty()) {
redoStack.pop();
}
}
void undo() {
if (!commandStack.empty()) {
auto command = commandStack.top();
commandStack.pop();
command->undo();
redoStack.push(command);
}
}
void redo() {
if (!redoStack.empty()) {
auto command = redoStack.top();
redoStack.pop();
command->execute();
commandStack.push(command);
}
}
};
int main() {
FileSystem fileSystem;
auto createFile = std::make_shared<CreateFileCommand>(fileSystem, "example.txt");
auto deleteFile = std::make_shared<DeleteFileCommand>(fileSystem, "example.txt");
auto renameFile = std::make_shared<RenameFileCommand>(fileSystem, "example.txt", "example1.txt");
CommandManager commandManager;
commandManager.executeCommand(createFile);
commandManager.executeCommand(renameFile);
commandManager.undo();
commandManager.redo();
commandManager.executeCommand(deleteFile);
commandManager.undo();
return 0;
}
总结
命令模式在开发中可以帮助我们将请求封装为对象,并提供对请求执行、撤销和重做的支持。