第十五章:令行禁止,运筹帷幄------Command的命令艺术
风云再起,命令将军登场
在Strategy展示完他那精妙的策略艺术后,Command令行禁止、宛如将军般走出。他腰挂令牌,目光如炬,每个动作都透露出威严与秩序。
"Strategy兄的算法选择确实精妙,"Command声如洪钟地说道,"但在请求封装和执行控制方面,需要更加统一的处理方式。诸位请看------"
Command从腰间取下一枚令牌,令牌在空中化作一道流光:"我的命令模式,专为解决请求的封装和执行问题而生!我将请求封装成对象,从而支持请求的队列、日志、撤销和重做操作!"
架构老人眼中闪过赞许之色:"善!Command,就请你为大家展示这命令艺术的精妙所在。"
命令模式的核心要义
Command面向众人,开始阐述他的武学真谛:
"在我的命令模式中,主要包含四个核心角色:"
"Command(命令):声明执行操作的接口。"
"ConcreteCommand(具体命令):将一个接收者对象绑定于一个动作,实现执行方法。"
"Invoker(调用者):要求命令执行请求。"
"Receiver(接收者):知道如何实施与执行一个请求相关的操作。"
"其精妙之处在于,"Command继续道,"命令对象将动作和接收者包进对象中,只暴露一个execute()方法。这样,命令对象可以被存储、传递、调用,甚至支持撤销和重做!"
C++实战:智能家居控制系统
"且让我以一个智能家居控制系统为例,展示命令模式的实战应用。"Command说着,手中凝聚出一道道代码流光。
基础框架搭建
首先,Command定义了命令接口:
cpp
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
#include <map>
#include <iomanip>
#include <sstream>
#include <random>
#include <thread>
#include <chrono>
#include <stack>
#include <queue>
// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
virtual std::string getName() const = 0;
virtual std::string getDescription() const = 0;
};
// 命令历史管理器
class CommandHistory {
private:
std::stack<std::unique_ptr<Command>> history_;
std::stack<std::unique_ptr<Command>> redoStack_;
public:
CommandHistory() {
std::cout << "📜 创建命令历史管理器" << std::endl;
}
void push(std::unique_ptr<Command> command) {
history_.push(std::move(command));
// 执行新命令时清空重做栈
while (!redoStack_.empty()) {
redoStack_.pop();
}
std::cout << "📝 记录命令到历史" << std::endl;
}
void undo() {
if (history_.empty()) {
std::cout << "❌ 没有可撤销的命令" << std::endl;
return;
}
auto command = std::move(history_.top());
history_.pop();
std::cout << "↩️ 撤销命令: " << command->getName() << std::endl;
command->undo();
redoStack_.push(std::move(command));
}
void redo() {
if (redoStack_.empty()) {
std::cout << "❌ 没有可重做的命令" << std::endl;
return;
}
auto command = std::move(redoStack_.top());
redoStack_.pop();
std::cout << "↪️ 重做命令: " << command->getName() << std::endl;
command->execute();
history_.push(std::move(command));
}
void clear() {
while (!history_.empty()) history_.pop();
while (!redoStack_.empty()) redoStack_.pop();
std::cout << "🧹 清空命令历史" << std::endl;
}
size_t getHistorySize() const { return history_.size(); }
size_t getRedoSize() const { return redoStack_.size(); }
void showStatus() const {
std::cout << "📊 命令历史状态: " << history_.size()
<< " 个已执行, " << redoStack_.size() << " 个可重做" << std::endl;
}
};
接收者实现
Command创建了各种智能家居设备:
cpp
// 接收者:灯光
class Light {
private:
std::string location_;
bool isOn_;
int brightness_; // 0-100
std::string color_;
public:
Light(const std::string& location)
: location_(location), isOn_(false), brightness_(50), color_("white") {
std::cout << "💡 创建灯光: " << location_ << std::endl;
}
void on() {
isOn_ = true;
std::cout << "🔆 " << location_ << " 灯光打开" << std::endl;
}
void off() {
isOn_ = false;
std::cout << "🌙 " << location_ << " 灯光关闭" << std::endl;
}
void setBrightness(int level) {
brightness_ = std::max(0, std::min(100, level));
std::cout << "☀️ " << location_ << " 亮度设置为: " << brightness_ << "%" << std::endl;
}
void setColor(const std::string& color) {
color_ = color;
std::cout << "🎨 " << location_ << " 颜色设置为: " << color_ << std::endl;
}
void dim() {
brightness_ = std::max(0, brightness_ - 10);
std::cout << "🔅 " << location_ << " 调暗到: " << brightness_ << "%" << std::endl;
}
void brighten() {
brightness_ = std::min(100, brightness_ + 10);
std::cout << "🔆 " << location_ << " 调亮到: " << brightness_ << "%" << std::endl;
}
std::string getStatus() const {
std::stringstream ss;
ss << location_ << " 灯光: " << (isOn_ ? "开" : "关")
<< " | 亮度: " << brightness_ << "%"
<< " | 颜色: " << color_;
return ss.str();
}
bool isOn() const { return isOn_; }
int getBrightness() const { return brightness_; }
std::string getColor() const { return color_; }
std::string getLocation() const { return location_; }
};
// 接收者:空调
class AirConditioner {
private:
std::string location_;
bool isOn_;
int temperature_; // 摄氏度
int fanSpeed_; // 1-5
std::string mode_; // "cool", "heat", "fan", "auto"
public:
AirConditioner(const std::string& location)
: location_(location), isOn_(false), temperature_(22), fanSpeed_(3), mode_("cool") {
std::cout << "❄️ 创建空调: " << location_ << std::endl;
}
void on() {
isOn_ = true;
std::cout << "🌀 " << location_ << " 空调打开" << std::endl;
}
void off() {
isOn_ = false;
std::cout << "💤 " << location_ << " 空调关闭" << std::endl;
}
void setTemperature(int temp) {
temperature_ = std::max(16, std::min(30, temp));
std::cout << "🌡️ " << location_ << " 温度设置为: " << temperature_ << "°C" << std::endl;
}
void setFanSpeed(int speed) {
fanSpeed_ = std::max(1, std::min(5, speed));
std::cout << "💨 " << location_ << " 风速设置为: " << fanSpeed_ << std::endl;
}
void setMode(const std::string& mode) {
mode_ = mode;
std::cout << "🎛️ " << location_ << " 模式设置为: " << mode_ << std::endl;
}
void increaseTemp() {
temperature_ = std::min(30, temperature_ + 1);
std::cout << "🌡️ " << location_ << " 温度升高到: " << temperature_ << "°C" << std::endl;
}
void decreaseTemp() {
temperature_ = std::max(16, temperature_ - 1);
std::cout << "🌡️ " << location_ << " 温度降低到: " << temperature_ << "°C" << std::endl;
}
std::string getStatus() const {
std::stringstream ss;
ss << location_ << " 空调: " << (isOn_ ? "开" : "关")
<< " | 温度: " << temperature_ << "°C"
<< " | 风速: " << fanSpeed_
<< " | 模式: " << mode_;
return ss.str();
}
bool isOn() const { return isOn_; }
int getTemperature() const { return temperature_; }
int getFanSpeed() const { return fanSpeed_; }
std::string getMode() const { return mode_; }
};
// 接收者:窗帘
class Curtain {
private:
std::string location_;
bool isOpen_;
int position_; // 0-100, 0=完全关闭, 100=完全打开
public:
Curtain(const std::string& location)
: location_(location), isOpen_(false), position_(0) {
std::cout << "🪟 创建窗帘: " << location_ << std::endl;
}
void open() {
isOpen_ = true;
position_ = 100;
std::cout << "🌅 " << location_ << " 窗帘打开" << std::endl;
}
void close() {
isOpen_ = false;
position_ = 0;
std::cout << "🌃 " << location_ << " 窗帘关闭" << std::endl;
}
void setPosition(int pos) {
position_ = std::max(0, std::min(100, pos));
isOpen_ = (position_ > 0);
std::cout << "🎚️ " << location_ << " 窗帘位置: " << position_ << "%" << std::endl;
}
void openPartially(int percent) {
setPosition(percent);
std::cout << "🪟 " << location_ << " 部分打开: " << percent << "%" << std::endl;
}
std::string getStatus() const {
std::stringstream ss;
ss << location_ << " 窗帘: " << (isOpen_ ? "开" : "关")
<< " | 位置: " << position_ << "%";
return ss.str();
}
bool isOpen() const { return isOpen_; }
int getPosition() const { return position_; }
};
// 接收者:音响系统
class Stereo {
private:
std::string location_;
bool isOn_;
int volume_; // 0-100
std::string source_; // "CD", "Radio", "Bluetooth", "Aux"
public:
Stereo(const std::string& location)
: location_(location), isOn_(false), volume_(30), source_("Radio") {
std::cout << "🔊 创建音响: " << location_ << std::endl;
}
void on() {
isOn_ = true;
std::cout << "🎵 " << location_ << " 音响打开" << std::endl;
}
void off() {
isOn_ = false;
std::cout << "🔇 " << location_ << " 音响关闭" << std::endl;
}
void setVolume(int level) {
volume_ = std::max(0, std::min(100, level));
std::cout << "🔊 " << location_ << " 音量设置为: " << volume_ << std::endl;
}
void setSource(const std::string& src) {
source_ = src;
std::cout << "📻 " << location_ << " 音源设置为: " << source_ << std::endl;
}
void volumeUp() {
volume_ = std::min(100, volume_ + 5);
std::cout << "🔊 " << location_ << " 音量增加到: " << volume_ << std::endl;
}
void volumeDown() {
volume_ = std::max(0, volume_ - 5);
std::cout << "🔊 " << location_ << " 音量减少到: " << volume_ << std::endl;
}
std::string getStatus() const {
std::stringstream ss;
ss << location_ << " 音响: " << (isOn_ ? "开" : "关")
<< " | 音量: " << volume_
<< " | 音源: " << source_;
return ss.str();
}
bool isOn() const { return isOn_; }
int getVolume() const { return volume_; }
std::string getSource() const { return source_; }
};
具体命令实现
Command创建了各种设备命令:
cpp
// 具体命令:灯光命令
class LightCommand : public Command {
protected:
Light& light_;
std::string name_;
public:
LightCommand(Light& light, const std::string& name)
: light_(light), name_(name) {}
std::string getName() const override {
return name_;
}
std::string getDescription() const override {
return "控制 " + light_.getLocation() + " 灯光";
}
};
class LightOnCommand : public LightCommand {
private:
int previousBrightness_;
std::string previousColor_;
bool wasOn_;
public:
LightOnCommand(Light& light) : LightCommand(light, "打开灯光") {
wasOn_ = light_.isOn();
previousBrightness_ = light_.getBrightness();
previousColor_ = light_.getColor();
}
void execute() override {
std::cout << "🚀 执行: " << getName() << std::endl;
wasOn_ = light_.isOn();
previousBrightness_ = light_.getBrightness();
previousColor_ = light_.getColor();
light_.on();
light_.setBrightness(80); // 默认亮度
light_.setColor("white"); // 默认颜色
}
void undo() override {
std::cout << "↩️ 撤销: " << getName() << std::endl;
if (!wasOn_) {
light_.off();
}
light_.setBrightness(previousBrightness_);
light_.setColor(previousColor_);
}
};
class LightOffCommand : public LightCommand {
private:
int previousBrightness_;
std::string previousColor_;
bool wasOn_;
public:
LightOffCommand(Light& light) : LightCommand(light, "关闭灯光") {
wasOn_ = light_.isOn();
previousBrightness_ = light_.getBrightness();
previousColor_ = light_.getColor();
}
void execute() override {
std::cout << "🚀 执行: " << getName() << std::endl;
wasOn_ = light_.isOn();
previousBrightness_ = light_.getBrightness();
previousColor_ = light_.getColor();
light_.off();
}
void undo() override {
std::cout << "↩️ 撤销: " << getName() << std::endl;
if (wasOn_) {
light_.on();
light_.setBrightness(previousBrightness_);
light_.setColor(previousColor_);
}
}
};
class LightDimCommand : public LightCommand {
private:
int previousBrightness_;
public:
LightDimCommand(Light& light) : LightCommand(light, "调暗灯光") {}
void execute() override {
std::cout << "🚀 执行: " << getName() << std::endl;
previousBrightness_ = light_.getBrightness();
light_.dim();
}
void undo() override {
std::cout << "↩️ 撤销: " << getName() << std::endl;
light_.setBrightness(previousBrightness_);
}
};
// 具体命令:空调命令
class AirConditionerCommand : public Command {
protected:
AirConditioner& ac_;
std::string name_;
public:
AirConditionerCommand(AirConditioner& ac, const std::string& name)
: ac_(ac), name_(name) {}
std::string getName() const override {
return name_;
}
std::string getDescription() const override {
return "控制 " + ac_.getLocation() + " 空调";
}
};
class AirConditionerOnCommand : public AirConditionerCommand {
private:
bool wasOn_;
int previousTemp_;
int previousFanSpeed_;
std::string previousMode_;
public:
AirConditionerOnCommand(AirConditioner& ac)
: AirConditionerCommand(ac, "打开空调") {}
void execute() override {
std::cout << "🚀 执行: " << getName() << std::endl;
wasOn_ = ac_.isOn();
previousTemp_ = ac_.getTemperature();
previousFanSpeed_ = ac_.getFanSpeed();
previousMode_ = ac_.getMode();
ac_.on();
ac_.setTemperature(24);
ac_.setFanSpeed(3);
ac_.setMode("cool");
}
void undo() override {
std::cout << "↩️ 撤销: " << getName() << std::endl;
if (!wasOn_) {
ac_.off();
} else {
ac_.setTemperature(previousTemp_);
ac_.setFanSpeed(previousFanSpeed_);
ac_.setMode(previousMode_);
}
}
};
class SetTemperatureCommand : public AirConditionerCommand {
private:
int targetTemp_;
int previousTemp_;
public:
SetTemperatureCommand(AirConditioner& ac, int temp)
: AirConditionerCommand(ac, "设置温度"), targetTemp_(temp) {}
void execute() override {
std::cout << "🚀 执行: " << getName() << " 到 " << targetTemp_ << "°C" << std::endl;
previousTemp_ = ac_.getTemperature();
ac_.setTemperature(targetTemp_);
}
void undo() override {
std::cout << "↩️ 撤销: " << getName() << std::endl;
ac_.setTemperature(previousTemp_);
}
};
// 具体命令:宏命令 - 一次执行多个命令
class MacroCommand : public Command {
private:
std::vector<std::unique_ptr<Command>> commands_;
std::string name_;
std::string description_;
public:
MacroCommand(const std::string& name, const std::string& description = "")
: name_(name), description_(description) {
std::cout << "📋 创建宏命令: " << name_ << std::endl;
}
void addCommand(std::unique_ptr<Command> command) {
commands_.push_back(std::move(command));
}
void execute() override {
std::cout << "🚀 执行宏命令: " << name_ << " (" << commands_.size() << " 个子命令)" << std::endl;
for (auto& cmd : commands_) {
cmd->execute();
}
}
void undo() override {
std::cout << "↩️ 撤销宏命令: " << name_ << std::endl;
// 按相反顺序撤销
for (auto it = commands_.rbegin(); it != commands_.rend(); ++it) {
(*it)->undo();
}
}
std::string getName() const override {
return name_;
}
std::string getDescription() const override {
return description_.empty() ?
"包含 " + std::to_string(commands_.size()) + " 个操作的宏命令" :
description_;
}
size_t getCommandCount() const {
return commands_.size();
}
};
调用者实现
Command创建了遥控器和智能家居控制器:
cpp
// 调用者:遥控器
class RemoteControl {
private:
std::vector<std::unique_ptr<Command>> onCommands_;
std::vector<std::unique_ptr<Command>> offCommands_;
std::unique_ptr<Command> undoCommand_;
CommandHistory& history_;
public:
RemoteControl(CommandHistory& history, int slotCount = 8)
: history_(history), undoCommand_(nullptr) {
// 初始化所有插槽为空命令
auto noCommand = std::make_unique<NoCommand>();
for (int i = 0; i < slotCount; i++) {
onCommands_.push_back(std::make_unique<NoCommand>());
offCommands_.push_back(std::make_unique<NoCommand>());
}
std::cout << "🎮 创建遥控器,包含 " << slotCount << " 个插槽" << std::endl;
}
void setCommand(int slot, std::unique_ptr<Command> onCommand,
std::unique_ptr<Command> offCommand) {
if (slot >= 0 && slot < onCommands_.size()) {
onCommands_[slot] = std::move(onCommand);
offCommands_[slot] = std::move(offCommand);
std::cout << "🔧 设置插槽 " << slot << " 命令" << std::endl;
}
}
void onButtonPressed(int slot) {
if (slot >= 0 && slot < onCommands_.size()) {
auto& command = onCommands_[slot];
command->execute();
history_.push(std::unique_ptr<Command>(new CommandWrapper(*command)));
}
}
void offButtonPressed(int slot) {
if (slot >= 0 && slot < offCommands_.size()) {
auto& command = offCommands_[slot];
command->execute();
history_.push(std::unique_ptr<Command>(new CommandWrapper(*command)));
}
}
void undoButtonPressed() {
history_.undo();
}
void redoButtonPressed() {
history_.redo();
}
void showControls() {
std::cout << "\n🎮 遥控器控制面板:" << std::endl;
std::cout << "==================" << std::endl;
for (size_t i = 0; i < onCommands_.size(); i++) {
std::cout << "插槽 " << i << ": [开] " << onCommands_[i]->getName()
<< " | [关] " << offCommands_[i]->getName() << std::endl;
}
std::cout << "特殊按钮: [撤销] | [重做]" << std::endl;
}
private:
// 空命令
class NoCommand : public Command {
public:
void execute() override {
std::cout << "⏹️ 空命令 - 无操作" << std::endl;
}
void undo() override {
std::cout << "⏹️ 空命令 - 无操作" << std::endl;
}
std::string getName() const override { return "空命令"; }
std::string getDescription() const override { return "不执行任何操作"; }
};
// 命令包装器,用于历史记录
class CommandWrapper : public Command {
private:
Command& originalCommand_;
public:
CommandWrapper(Command& cmd) : originalCommand_(cmd) {}
void execute() override {
originalCommand_.execute();
}
void undo() override {
originalCommand_.undo();
}
std::string getName() const override {
return originalCommand_.getName();
}
std::string getDescription() const override {
return originalCommand_.getDescription();
}
};
};
// 调用者:语音助手
class VoiceAssistant {
private:
std::map<std::string, std::unique_ptr<Command>> voiceCommands_;
CommandHistory& history_;
public:
VoiceAssistant(CommandHistory& history) : history_(history) {
std::cout << "🎤 创建语音助手" << std::endl;
}
void registerCommand(const std::string& voiceCommand, std::unique_ptr<Command> command) {
voiceCommands_[voiceCommand] = std::move(command);
std::cout << "🗣️ 注册语音命令: \"" << voiceCommand << "\" -> "
<< voiceCommands_[voiceCommand]->getName() << std::endl;
}
void processVoiceCommand(const std::string& command) {
auto it = voiceCommands_.find(command);
if (it != voiceCommands_.end()) {
std::cout << "🎤 语音识别: \"" << command << "\"" << std::endl;
it->second->execute();
// 简化:不记录到历史
} else {
std::cout << "❌ 未知语音命令: \"" << command << "\"" << std::endl;
}
}
void showVoiceCommands() {
std::cout << "\n🗣️ 可用语音命令:" << std::endl;
for (const auto& pair : voiceCommands_) {
std::cout << " \"" << pair.first << "\" -> " << pair.second->getDescription() << std::endl;
}
}
};
UML 武功秘籍图
controls uses manages contains <<interface>> Command +execute() : void +undo() : void +getName() : string +getDescription() : string Light -string location_ -bool isOn_ -int brightness_ -string color_ +on() : void +off() : void +setBrightness(int) : void +setColor(string) : void +getStatus() : string LightOnCommand -Light& light_ -string name_ -int previousBrightness_ -string previousColor_ -bool wasOn_ +execute() : void +undo() : void +getName() : string +getDescription() : string MacroCommand -vector<unique_ptr>Command<> commands_ -string name_ -string description_ +addCommand(unique_ptr<Command>) : void +execute() : void +undo() : void +getName() : string +getDescription() : string RemoteControl -vector<unique_ptr>Command<> onCommands_ -vector<unique_ptr>Command<> offCommands_ -unique_ptr<Command> undoCommand_ -CommandHistory& history_ +setCommand(int, unique_ptr<Command>, unique_ptr<Command>) : void +onButtonPressed(int) : void +offButtonPressed(int) : void +undoButtonPressed() : void +showControls() : void CommandHistory -stack<unique_ptr>Command<> history_ -stack<unique_ptr>Command<> redoStack_ +push(unique_ptr<Command>) : void +undo() : void +redo() : void +clear() : void
实战演练:高级命令系统
Command继续展示更复杂的命令模式应用:
cpp
// 命令队列和调度器
class CommandScheduler {
private:
std::queue<std::unique_ptr<Command>> commandQueue_;
bool isRunning_;
std::thread workerThread_;
std::mutex queueMutex_;
std::condition_variable condition_;
CommandHistory& history_;
public:
CommandScheduler(CommandHistory& history) : history_(history), isRunning_(false) {
std::cout << "⏰ 创建命令调度器" << std::endl;
}
~CommandScheduler() {
stop();
}
void start() {
if (isRunning_) return;
isRunning_ = true;
workerThread_ = std::thread(&CommandScheduler::workerLoop, this);
std::cout << "▶️ 启动命令调度器" << std::endl;
}
void stop() {
if (!isRunning_) return;
isRunning_ = false;
condition_.notify_all();
if (workerThread_.joinable()) {
workerThread_.join();
}
std::cout << "⏹️ 停止命令调度器" << std::endl;
}
void scheduleCommand(std::unique_ptr<Command> command) {
std::lock_guard<std::mutex> lock(queueMutex_);
commandQueue_.push(std::move(command));
condition_.notify_one();
std::cout << "📅 调度命令: " << commandQueue_.back()->getName() << std::endl;
}
void scheduleDelayedCommand(std::unique_ptr<Command> command,
std::chrono::milliseconds delay) {
std::thread([this, cmd = std::move(command), delay]() mutable {
std::this_thread::sleep_for(delay);
scheduleCommand(std::move(cmd));
}).detach();
}
size_t getQueueSize() const {
return commandQueue_.size();
}
void clearQueue() {
std::lock_guard<std::mutex> lock(queueMutex_);
while (!commandQueue_.empty()) {
commandQueue_.pop();
}
std::cout << "🧹 清空命令队列" << std::endl;
}
private:
void workerLoop() {
while (isRunning_) {
std::unique_ptr<Command> command;
{
std::unique_lock<std::mutex> lock(queueMutex_);
condition_.wait(lock, [this]() {
return !isRunning_ || !commandQueue_.empty();
});
if (!isRunning_ && commandQueue_.empty()) {
break;
}
if (!commandQueue_.empty()) {
command = std::move(commandQueue_.front());
commandQueue_.pop();
}
}
if (command) {
std::cout << "🎬 执行调度命令: " << command->getName() << std::endl;
command->execute();
history_.push(std::move(command));
}
}
}
};
// 命令日志记录器
class CommandLogger {
private:
std::vector<std::string> logEntries_;
std::string logFile_;
public:
CommandLogger(const std::string& logFile = "command_log.txt")
: logFile_(logFile) {
std::cout << "📋 创建命令日志记录器: " << logFile_ << std::endl;
}
void logCommandExecution(const Command& command, bool executed = true) {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << "[" << std::ctime(&time);
ss.seekp(-1, std::ios_base::end); // 移除换行符
ss << "] " << (executed ? "执行" : "撤销") << ": "
<< command.getName() << " - " << command.getDescription();
std::string logEntry = ss.str();
logEntries_.push_back(logEntry);
std::cout << "📝 " << logEntry << std::endl;
// 写入文件(简化实现)
// 在实际应用中,这里会写入文件
}
void showLog(int count = 10) const {
int start = std::max(0, static_cast<int>(logEntries_.size()) - count);
std::cout << "\n📜 最近 " << (logEntries_.size() - start) << " 条命令日志:" << std::endl;
for (int i = start; i < logEntries_.size(); ++i) {
std::cout << " " << logEntries_[i] << std::endl;
}
}
void clearLog() {
logEntries_.clear();
std::cout << "🧹 清空命令日志" << std::endl;
}
size_t getLogSize() const {
return logEntries_.size();
}
};
// 支持事务的命令
class TransactionalCommand : public Command {
protected:
CommandLogger& logger_;
std::string name_;
std::string description_;
public:
TransactionalCommand(CommandLogger& logger, const std::string& name,
const std::string& description = "")
: logger_(logger), name_(name), description_(description) {}
void execute() override {
if (performExecute()) {
logger_.logCommandExecution(*this, true);
std::cout << "✅ 事务命令执行成功: " << name_ << std::endl;
} else {
std::cout << "❌ 事务命令执行失败: " << name_ << std::endl;
}
}
void undo() override {
if (performUndo()) {
logger_.logCommandExecution(*this, false);
std::cout << "✅ 事务命令撤销成功: " << name_ << std::endl;
} else {
std::cout << "❌ 事务命令撤销失败: " << name_ << std::endl;
}
}
std::string getName() const override {
return name_;
}
std::string getDescription() const override {
return description_;
}
protected:
virtual bool performExecute() = 0;
virtual bool performUndo() = 0;
};
// 智能场景管理器
class SmartSceneManager {
private:
std::map<std::string, std::unique_ptr<MacroCommand>> scenes_;
CommandHistory& history_;
CommandLogger& logger_;
public:
SmartSceneManager(CommandHistory& history, CommandLogger& logger)
: history_(history), logger_(logger) {
std::cout << "🎭 创建智能场景管理器" << std::endl;
}
void createScene(const std::string& sceneName, const std::string& description = "") {
auto scene = std::make_unique<MacroCommand>(sceneName, description);
scenes_[sceneName] = std::move(scene);
std::cout << "🎨 创建场景: " << sceneName << std::endl;
}
void addCommandToScene(const std::string& sceneName, std::unique_ptr<Command> command) {
auto it = scenes_.find(sceneName);
if (it != scenes_.end()) {
it->second->addCommand(std::move(command));
std::cout << "➕ 添加命令到场景 " << sceneName << std::endl;
}
}
void activateScene(const std::string& sceneName) {
auto it = scenes_.find(sceneName);
if (it != scenes_.end()) {
std::cout << "🎭 激活场景: " << sceneName << std::endl;
it->second->execute();
history_.push(std::unique_ptr<Command>(new MacroCommandWrapper(*(it->second))));
logger_.logCommandExecution(*(it->second), true);
} else {
std::cout << "❌ 未知场景: " << sceneName << std::endl;
}
}
void listScenes() const {
std::cout << "\n🎭 可用场景 (" << scenes_.size() << " 个):" << std::endl;
for (const auto& pair : scenes_) {
std::cout << " • " << pair.first << " ("
<< pair.second->getCommandCount() << " 个命令) - "
<< pair.second->getDescription() << std::endl;
}
}
private:
class MacroCommandWrapper : public Command {
private:
MacroCommand& originalMacro_;
public:
MacroCommandWrapper(MacroCommand& macro) : originalMacro_(macro) {}
void execute() override {
originalMacro_.execute();
}
void undo() override {
originalMacro_.undo();
}
std::string getName() const override {
return originalMacro_.getName();
}
std::string getDescription() const override {
return originalMacro_.getDescription();
}
};
};
完整测试代码
cpp
// 测试命令模式
void testCommandPattern() {
std::cout << "=== 命令模式测试开始 ===" << std::endl;
// 创建命令历史
CommandHistory history;
// 创建设备
Light livingRoomLight("客厅");
Light bedroomLight("卧室");
AirConditioner livingRoomAC("客厅");
Curtain livingRoomCurtain("客厅");
Stereo livingRoomStereo("客厅");
// 创建命令
auto livingRoomLightOn = std::make_unique<LightOnCommand>(livingRoomLight);
auto livingRoomLightOff = std::make_unique<LightOffCommand>(livingRoomLight);
auto livingRoomLightDim = std::make_unique<LightDimCommand>(livingRoomLight);
auto bedroomLightOn = std::make_unique<LightOnCommand>(bedroomLight);
auto bedroomLightOff = std::make_unique<LightOffCommand>(bedroomLight);
auto acOn = std::make_unique<AirConditionerOnCommand>(livingRoomAC);
auto setTemp24 = std::make_unique<SetTemperatureCommand>(livingRoomAC, 24);
auto curtainOpen = std::make_unique<CurtainOpenCommand>(livingRoomCurtain);
auto curtainClose = std::make_unique<CurtainCloseCommand>(livingRoomCurtain);
// 测试基础命令
std::cout << "\n--- 基础命令测试 ---" << std::endl;
livingRoomLightOn->execute();
history.push(std::move(livingRoomLightOn));
acOn->execute();
history.push(std::move(acOn));
curtainOpen->execute();
history.push(std::move(curtainOpen));
// 测试撤销
std::cout << "\n--- 撤销操作测试 ---" << std::endl;
history.undo();
history.undo();
history.undo();
// 测试重做
std::cout << "\n--- 重做操作测试 ---" << std::endl;
history.redo();
history.redo();
history.redo();
std::cout << "\n=== 基础命令模式测试结束 ===" << std::endl;
}
// 测试宏命令
void testMacroCommands() {
std::cout << "\n=== 宏命令测试开始 ===" << std::endl;
CommandHistory history;
// 创建设备
Light livingRoomLight("客厅");
Light bedroomLight("卧室");
AirConditioner livingRoomAC("客厅");
Curtain livingRoomCurtain("客厅");
Stereo livingRoomStereo("客厅");
// 创建回家场景宏命令
auto homeScene = std::make_unique<MacroCommand>("回家场景", "模拟回家时的设备状态");
homeScene->addCommand(std::make_unique<LightOnCommand>(livingRoomLight));
homeScene->addCommand(std::make_unique<LightOnCommand>(bedroomLight));
homeScene->addCommand(std::make_unique<AirConditionerOnCommand>(livingRoomAC));
homeScene->addCommand(std::make_unique<CurtainOpenCommand>(livingRoomCurtain));
// 创建离家场景宏命令
auto awayScene = std::make_unique<MacroCommand>("离家场景", "模拟离家时的设备状态");
awayScene->addCommand(std::make_unique<LightOffCommand>(livingRoomLight));
awayScene->addCommand(std::make_unique<LightOffCommand>(bedroomLight));
awayScene->addCommand(std::make_unique<AirConditionerOffCommand>(livingRoomAC));
awayScene->addCommand(std::make_unique<CurtainCloseCommand>(livingRoomCurtain));
std::cout << "\n--- 测试回家场景 ---" << std::endl;
homeScene->execute();
history.push(std::move(homeScene));
std::cout << "\n--- 测试离家场景 ---" << std::endl;
awayScene->execute();
history.push(std::move(awayScene));
std::cout << "\n--- 撤销场景 ---" << std::endl;
history.undo();
std::cout << "\n=== 宏命令测试结束 ===" << std::endl;
}
// 测试遥控器
void testRemoteControl() {
std::cout << "\n=== 遥控器测试开始 ===" << std::endl;
CommandHistory history;
RemoteControl remote(history, 4);
// 创建设备
Light livingRoomLight("客厅");
AirConditioner livingRoomAC("客厅");
Curtain livingRoomCurtain("客厅");
Stereo livingRoomStereo("客厅");
// 设置遥控器命令
remote.setCommand(0,
std::make_unique<LightOnCommand>(livingRoomLight),
std::make_unique<LightOffCommand>(livingRoomLight));
remote.setCommand(1,
std::make_unique<AirConditionerOnCommand>(livingRoomAC),
std::make_unique<AirConditionerOffCommand>(livingRoomAC));
remote.setCommand(2,
std::make_unique<CurtainOpenCommand>(livingRoomCurtain),
std::make_unique<CurtainCloseCommand>(livingRoomCurtain));
auto stereoOn = std::make_unique<StereoOnCommand>(livingRoomStereo);
auto stereoOff = std::make_unique<StereoOffCommand>(livingRoomStereo);
remote.setCommand(3, std::move(stereoOn), std::move(stereoOff));
// 显示遥控器控制
remote.showControls();
// 测试遥控器操作
std::cout << "\n--- 测试遥控器操作 ---" << std::endl;
remote.onButtonPressed(0); // 打开客厅灯
remote.onButtonPressed(1); // 打开空调
remote.onButtonPressed(2); // 打开窗帘
remote.onButtonPressed(3); // 打开音响
std::cout << "\n--- 测试撤销 ---" << std::endl;
remote.undoButtonPressed(); // 撤销音响
remote.undoButtonPressed(); // 撤销窗帘
std::cout << "\n--- 测试重做 ---" << std::endl;
remote.redoButtonPressed(); // 重做窗帘
remote.redoButtonPressed(); // 重做音响
std::cout << "\n=== 遥控器测试结束 ===" << std::endl;
}
// 测试高级功能
void testAdvancedFeatures() {
std::cout << "\n=== 高级功能测试开始 ===" << std::endl;
CommandHistory history;
CommandLogger logger;
CommandScheduler scheduler(history);
SmartSceneManager sceneManager(history, logger);
// 创建设备
Light livingRoomLight("客厅");
Light bedroomLight("卧室");
AirConditioner livingRoomAC("客厅");
// 创建场景
sceneManager.createScene("早晨场景", "早晨起床时的设备状态");
sceneManager.addCommandToScene("早晨场景",
std::make_unique<LightOnCommand>(livingRoomLight));
sceneManager.addCommandToScene("早晨场景",
std::make_unique<SetTemperatureCommand>(livingRoomAC, 22));
sceneManager.addCommandToScene("早晨场景",
std::make_unique<CurtainOpenCommand>(livingRoomCurtain));
sceneManager.createScene("夜晚场景", "晚上睡觉时的设备状态");
sceneManager.addCommandToScene("夜晚场景",
std::make_unique<LightOffCommand>(livingRoomLight));
sceneManager.addCommandToScene("夜晚场景",
std::make_unique<LightOffCommand>(bedroomLight));
sceneManager.addCommandToScene("夜晚场景",
std::make_unique<SetTemperatureCommand>(livingRoomAC, 20));
// 列出场景
sceneManager.listScenes();
// 测试场景
std::cout << "\n--- 测试早晨场景 ---" << std::endl;
sceneManager.activateScene("早晨场景");
std::cout << "\n--- 测试夜晚场景 ---" << std::endl;
sceneManager.activateScene("夜晚场景");
// 测试命令调度
std::cout << "\n--- 测试命令调度 ---" << std::endl;
scheduler.start();
scheduler.scheduleCommand(std::make_unique<LightOnCommand>(livingRoomLight));
scheduler.scheduleDelayedCommand(
std::make_unique<LightOffCommand>(livingRoomLight),
std::chrono::seconds(2));
// 等待调度完成
std::this_thread::sleep_for(std::chrono::seconds(3));
scheduler.stop();
// 显示日志
std::cout << "\n--- 命令执行日志 ---" << std::endl;
logger.showLog();
std::cout << "\n=== 高级功能测试结束 ===" << std::endl;
}
// 实战应用:智能家居控制系统
class SmartHomeSystem {
private:
CommandHistory history_;
CommandLogger logger_;
CommandScheduler scheduler_;
SmartSceneManager sceneManager_;
RemoteControl remote_;
VoiceAssistant voiceAssistant_;
// 设备
Light livingRoomLight_;
Light bedroomLight_;
Light kitchenLight_;
AirConditioner livingRoomAC_;
AirConditioner bedroomAC_;
Curtain livingRoomCurtain_;
Curtain bedroomCurtain_;
Stereo livingRoomStereo_;
public:
SmartHomeSystem()
: history_(), logger_(), scheduler_(history_),
sceneManager_(history_, logger_), remote_(history_, 6),
voiceAssistant_(history_),
livingRoomLight_("客厅"), bedroomLight_("卧室"), kitchenLight_("厨房"),
livingRoomAC_("客厅"), bedroomAC_("卧室"),
livingRoomCurtain_("客厅"), bedroomCurtain_("卧室"),
livingRoomStereo_("客厅") {
std::cout << "🏠 创建智能家居系统" << std::endl;
initializeSystem();
}
void initializeSystem() {
// 初始化遥控器
setupRemoteControl();
// 初始化语音命令
setupVoiceCommands();
// 初始化场景
setupScenes();
// 启动调度器
scheduler_.start();
std::cout << "✅ 智能家居系统初始化完成" << std::endl;
}
void setupRemoteControl() {
// 设置遥控器命令
remote_.setCommand(0,
std::make_unique<LightOnCommand>(livingRoomLight_),
std::make_unique<LightOffCommand>(livingRoomLight_));
remote_.setCommand(1,
std::make_unique<AirConditionerOnCommand>(livingRoomAC_),
std::make_unique<AirConditionerOffCommand>(livingRoomAC_));
remote_.setCommand(2,
std::make_unique<CurtainOpenCommand>(livingRoomCurtain_),
std::make_unique<CurtainCloseCommand>(livingRoomCurtain_));
remote_.setCommand(3,
std::make_unique<StereoOnCommand>(livingRoomStereo_),
std::make_unique<StereoOffCommand>(livingRoomStereo_));
// 宏命令插槽
auto allLightsOn = std::make_unique<MacroCommand>("所有灯光打开");
allLightsOn->addCommand(std::make_unique<LightOnCommand>(livingRoomLight_));
allLightsOn->addCommand(std::make_unique<LightOnCommand>(bedroomLight_));
allLightsOn->addCommand(std::make_unique<LightOnCommand>(kitchenLight_));
auto allLightsOff = std::make_unique<MacroCommand>("所有灯光关闭");
allLightsOff->addCommand(std::make_unique<LightOffCommand>(livingRoomLight_));
allLightsOff->addCommand(std::make_unique<LightOffCommand>(bedroomLight_));
allLightsOff->addCommand(std::make_unique<LightOffCommand>(kitchenLight_));
remote_.setCommand(4, std::move(allLightsOn), std::move(allLightsOff));
std::cout << "🎮 遥控器设置完成" << std::endl;
}
void setupVoiceCommands() {
voiceAssistant_.registerCommand("打开客厅灯",
std::make_unique<LightOnCommand>(livingRoomLight_));
voiceAssistant_.registerCommand("关闭客厅灯",
std::make_unique<LightOffCommand>(livingRoomLight_));
voiceAssistant_.registerCommand("打开空调",
std::make_unique<AirConditionerOnCommand>(livingRoomAC_));
voiceAssistant_.registerCommand("温度调高",
std::make_unique<AirConditionerTempUpCommand>(livingRoomAC_));
voiceAssistant_.registerCommand("温度调低",
std::make_unique<AirConditionerTempDownCommand>(livingRoomAC_));
std::cout.println("🎤 语音命令设置完成");
}
void setupScenes() {
// 回家场景
sceneManager_.createScene("回家", "回家时自动设置的场景");
sceneManager_.addCommandToScene("回家",
std::make_unique<LightOnCommand>(livingRoomLight_));
sceneManager_.addCommandToScene("回家",
std::make_unique<SetTemperatureCommand>(livingRoomAC_, 24));
sceneManager_.addCommandToScene("回家",
std::make_unique<CurtainOpenCommand>(livingRoomCurtain_));
sceneManager_.addCommandToScene("回家",
std::make_unique<StereoOnCommand>(livingRoomStereo_));
// 电影场景
sceneManager_.createScene("电影", "观看电影时的最佳环境");
sceneManager_.addCommandToScene("电影",
std::make_unique<LightDimCommand>(livingRoomLight_));
sceneManager_.addCommandToScene("电影",
std::make_unique<SetTemperatureCommand>(livingRoomAC_, 22));
sceneManager_.addCommandToScene("电影",
std::make_unique<CurtainCloseCommand>(livingRoomCurtain_));
sceneManager_.addCommandToScene("电影",
std::make_unique<StereoOnCommand>(livingRoomStereo_));
// 睡眠场景
sceneManager_.createScene("睡眠", "准备睡觉时的环境");
sceneManager_.addCommandToScene("睡眠",
std::make_unique<LightOffCommand>(livingRoomLight_));
sceneManager_.addCommandToScene("睡眠",
std::make_unique<LightOffCommand>(bedroomLight_));
sceneManager_.addCommandToScene("睡眠",
std::make_unique<SetTemperatureCommand>(livingRoomAC_, 20));
sceneManager_.addCommandToScene("睡眠",
std::make_unique<SetTemperatureCommand>(bedroomAC_, 20));
sceneManager_.addCommandToScene("睡眠",
std::make_unique<CurtainCloseCommand>(livingRoomCurtain_));
sceneManager_.addCommandToScene("睡眠",
std::make_unique<CurtainCloseCommand>(bedroomCurtain_));
std::cout << "🎭 场景设置完成" << std::endl;
}
void runDemo() {
std::cout << "\n🎮 运行智能家居演示..." << std::endl;
std::cout << "====================" << std::endl;
// 显示系统状态
showSystemStatus();
// 测试遥控器
std::cout << "\n--- 遥控器测试 ---" << std::endl;
remote_.showControls();
remote_.onButtonPressed(0); // 打开客厅灯
remote_.onButtonPressed(1); // 打开空调
remote_.onButtonPressed(4); // 所有灯光打开
// 测试语音控制
std::cout << "\n--- 语音控制测试 ---" << std::endl;
voiceAssistant_.showVoiceCommands();
voiceAssistant_.processVoiceCommand("打开客厅灯");
voiceAssistant_.processVoiceCommand("温度调高");
// 测试场景
std::cout << "\n--- 场景测试 ---" << std::endl;
sceneManager_.listScenes();
sceneManager_.activateScene("电影");
// 测试撤销
std::cout << "\n--- 撤销操作测试 ---" << std::endl;
remote_.undoButtonPressed();
remote_.undoButtonPressed();
// 显示最终状态
std::cout << "\n--- 最终系统状态 ---" << std::endl;
showSystemStatus();
logger_.showLog(5);
history_.showStatus();
}
void showSystemStatus() {
std::cout << "\n📊 智能家居系统状态" << std::endl;
std::cout << "==================" << std::endl;
std::cout << livingRoomLight_.getStatus() << std::endl;
std::cout << bedroomLight_.getStatus() << std::endl;
std::cout << kitchenLight_.getStatus() << std::endl;
std::cout << livingRoomAC_.getStatus() << std::endl;
std::cout << bedroomAC_.getStatus() << std::endl;
std::cout << livingRoomCurtain_.getStatus() << std::endl;
std::cout << bedroomCurtain_.getStatus() << std::endl;
std::cout << livingRoomStereo_.getStatus() << std::endl;
}
~SmartHomeSystem() {
scheduler_.stop();
std::cout << "🏠 关闭智能家居系统" << std::endl;
}
};
int main() {
std::cout << "🌈 设计模式武林大会 - 命令模式演示 🌈" << std::endl;
std::cout << "=====================================" << std::endl;
// 测试基础命令模式
testCommandPattern();
// 测试宏命令
testMacroCommands();
// 测试遥控器
testRemoteControl();
// 测试高级功能
testAdvancedFeatures();
// 运行智能家居系统演示
std::cout << "\n=== 智能家居系统演示 ===" << std::endl;
SmartHomeSystem smartHome;
smartHome.runDemo();
std::cout << "\n🎉 命令模式演示全部完成!" << std::endl;
return 0;
}
命令模式的武学心得
适用场景
- 请求队列:需要将请求排队、记录请求日志、支持可撤销操作时
- 回调机制:需要在不同时间点指定、排队和执行请求时
- 菜单系统:需要支持菜单项、按钮等用户界面元素时
- 事务系统:需要实现事务操作,支持回滚时
- 宏命令:需要支持批量操作和复杂操作序列时
优点
- 解耦调用者和接收者:调用者不需要知道接收者的具体实现
- 支持撤销和重做:可以轻松实现命令的撤销和重做功能
- 支持命令队列:可以将命令排队执行
- 支持日志记录:可以记录命令执行历史
- 支持宏命令:可以组合多个命令形成复杂操作
缺点
- 类数量增加:每个命令都需要一个具体的命令类
- 复杂度增加:对于简单操作,可能显得过于复杂
- 执行开销:命令对象的创建和执行可能带来额外开销
武林高手的点评
Template Method 赞叹道:"Command 兄的请求封装确实精妙!能够如此优雅地支持撤销、重做和命令队列,这在需要操作历史的系统中确实无人能及。"
Memento 也点头称赞:"Command 兄专注于操作命令的封装和执行,而我更关注对象状态的保存和恢复。我们都支持撤销操作,但关注点不同。"
Command 谦虚回应:"诸位过奖了。每个模式都有其适用场景。在需要封装操作请求并支持复杂控制时,我的命令模式确实能发挥重要作用。但在需要保存和恢复对象状态时,Memento 兄的方法更加合适。"
下章预告
在Command展示完他那精妙的命令艺术后,Template Method 老成持重地走出,手持一卷蓝图。
"Command 兄的请求封装确实精妙,但在算法结构固定、部分步骤需要变化的情况下,需要更加模板化的处理方式。" Template Method 沉稳地说道,"下一章,我将展示如何通过模板方法模式定义算法的骨架,将某些步骤延迟到子类中实现!"
架构老人满意地点头:"善!算法的模板化设计确实是代码复用的关键。下一章,就请 Template Method 展示他的模板艺术!"
欲知 Template Method 如何通过模板方法模式实现算法的灵活扩展,且听下回分解!