命令模式C++

命令模式(Command Pattern)是一種行為型設計模式,它將請求封裝為一個對象,使你可以用不同的請求對客戶進行參數化,還能支持請求的排隊、記錄日志及撤銷操作。這種模式將發送者和接收者解耦,發送者無需知道接收者的具體實現。

命令模式的核心角色

  1. Command(命令接口):聲明執行操作的接口(通常是execute()方法)
  2. ConcreteCommand(具體命令):實現命令接口,綁定接收者和具體操作
  3. Receiver(接收者):執行命令所對應的操作,知道如何實施具體行為
  4. Invoker(調用者):要求命令執行請求,持有命令對象
  5. Client(客戶端):創建具體命令對象并設置其接收者

C++實現示例

以下以"智能家居控制系統"為例實現命令模式,支持對燈光、電視等設備的操作,以及命令的撤銷功能:

#include <iostream>
#include <string>
#include <vector>
#include <memory>// 前向聲明接收者類
class Light;
class Television;// 命令接口
class Command {
public:virtual ~Command() = default;virtual void execute() = 0;virtual void undo() = 0;virtual std::string getName() const = 0;
};// 接收者1:燈光
class Light {
private:std::string location;bool isOn;public:Light(std::string loc) : location(std::move(loc)), isOn(false) {}void on() {isOn = true;std::cout << location << "燈光 打開" << std::endl;}void off() {isOn = false;std::cout << location << "燈光 關閉" << std::endl;}bool getState() const {return isOn;}
};// 接收者2:電視
class Television {
private:std::string location;bool isOn;int channel;int volume;public:Television(std::string loc) : location(std::move(loc)), isOn(false), channel(1), volume(5) {}void on() {isOn = true;std::cout << location << "電視 打開" << std::endl;}void off() {isOn = false;std::cout << location << "電視 關閉" << std::endl;}void setChannel(int ch) {channel = ch;std::cout << location << "電視 頻道設置為: " << channel << std::endl;}void setVolume(int vol) {volume = vol;std::cout << location << "電視 音量設置為: " << volume << std::endl;}bool getState() const {return isOn;}int getChannel() const {return channel;}int getVolume() const {return volume;}
};// 具體命令1:開燈
class LightOnCommand : public Command {
private:Light* light;bool previousState;  // 用于撤銷操作public:LightOnCommand(Light* l) : light(l) {}void execute() override {previousState = light->getState();light->on();}void undo() override {if (previousState) {light->on();} else {light->off();}std::cout << "撤銷 " << getName() << std::endl;}std::string getName() const override {return light->getState() ? "開燈" : "關燈";}
};// 具體命令2:關燈
class LightOffCommand : public Command {
private:Light* light;bool previousState;public:LightOffCommand(Light* l) : light(l) {}void execute() override {previousState = light->getState();light->off();}void undo() override {if (previousState) {light->on();} else {light->off();}std::cout << "撤銷 " << getName() << std::endl;}std::string getName() const override {return "關燈";}
};// 具體命令3:開電視
class TvOnCommand : public Command {
private:Television* tv;bool previousState;int previousChannel;int previousVolume;public:TvOnCommand(Television* t) : tv(t) {}void execute() override {previousState = tv->getState();previousChannel = tv->getChannel();previousVolume = tv->getVolume();tv->on();tv->setChannel(5);  // 默認打開5頻道tv->setVolume(7);   // 默認音量7}void undo() override {if (previousState) {tv->on();tv->setChannel(previousChannel);tv->setVolume(previousVolume);} else {tv->off();}std::cout << "撤銷 " << getName() << std::endl;}std::string getName() const override {return "開電視";}
};// 具體命令4:關電視
class TvOffCommand : public Command {
private:Television* tv;bool previousState;public:TvOffCommand(Television* t) : tv(t) {}void execute() override {previousState = tv->getState();tv->off();}void undo() override {if (previousState) {tv->on();} else {tv->off();}std::cout << "撤銷 " << getName() << std::endl;}std::string getName() const override {return "關電視";}
};// 調用者:遙控器
class RemoteControl {
private:std::vector<std::unique_ptr<Command>> onCommands;std::vector<std::unique_ptr<Command>> offCommands;std::unique_ptr<Command> undoCommand;  // 記錄上一個命令用于撤銷public:RemoteControl(int slotCount) {// 初始化命令槽位onCommands.resize(slotCount);offCommands.resize(slotCount);}// 設置命令void setCommand(int slot, std::unique_ptr<Command> onCmd, std::unique_ptr<Command> offCmd) {if (slot >= 0 && slot < onCommands.size()) {onCommands[slot] = std::move(onCmd);offCommands[slot] = std::move(offCmd);}}// 按下開按鈕void pressOnButton(int slot) {if (slot >= 0 && slot < onCommands.size() && onCommands[slot]) {onCommands[slot]->execute();undoCommand = std::move(onCommands[slot]);  // 保存命令用于撤銷}}// 按下關按鈕void pressOffButton(int slot) {if (slot >= 0 && slot < offCommands.size() && offCommands[slot]) {offCommands[slot]->execute();undoCommand = std::move(offCommands[slot]);  // 保存命令用于撤銷}}// 按下撤銷按鈕void pressUndoButton() {if (undoCommand) {undoCommand->undo();} else {std::cout << "沒有可撤銷的操作" << std::endl;}}
};// 客戶端代碼
int main() {// 創建接收者Light* livingRoomLight = new Light("客廳");Light* bedroomLight = new Light("臥室");Television* livingRoomTv = new Television("客廳");// 創建命令auto livingRoomLightOn = std::make_unique<LightOnCommand>(livingRoomLight);auto livingRoomLightOff = std::make_unique<LightOffCommand>(livingRoomLight);auto bedroomLightOn = std::make_unique<LightOnCommand>(bedroomLight);auto bedroomLightOff = std::make_unique<LightOffCommand>(bedroomLight);auto tvOn = std::make_unique<TvOnCommand>(livingRoomTv);auto tvOff = std::make_unique<TvOffCommand>(livingRoomTv);// 創建遙控器(調用者),有3個槽位RemoteControl remote(3);// 給遙控器設置命令remote.setCommand(0, std::move(livingRoomLightOn), std::move(livingRoomLightOff));remote.setCommand(1, std::move(bedroomLightOn), std::move(bedroomLightOff));remote.setCommand(2, std::move(tvOn), std::move(tvOff));// 測試操作std::cout << "=== 執行一系列操作 ===" << std::endl;remote.pressOnButton(0);   // 開客廳燈remote.pressOnButton(2);   // 開客廳電視remote.pressOffButton(0);  // 關客廳燈remote.pressOnButton(1);   // 開臥室燈// 測試撤銷std::cout << "\n=== 測試撤銷操作 ===" << std::endl;remote.pressUndoButton();  // 撤銷"開臥室燈"remote.pressUndoButton();  // 撤銷"關客廳燈"remote.pressUndoButton();  // 撤銷"開客廳電視"// 清理資源delete livingRoomLight;delete bedroomLight;delete livingRoomTv;return 0;
}

代碼解析

  1. 命令接口(Command:定義了execute()(執行命令)和undo()(撤銷命令)方法,所有具體命令都需實現這兩個方法。

  2. 接收者(LightTelevision:實現具體的業務邏輯(如開燈、關燈、開電視等),命令對象會調用這些方法。

  3. 具體命令

    • 每個命令類綁定一個接收者和對應的操作(如LightOnCommand綁定Lighton()方法)
    • 實現execute()方法調用接收者的相應操作,并保存執行前的狀態用于undo()
  4. 調用者(RemoteControl

    • 持有多個命令對象(開/關命令對),通過按鈕觸發命令執行
    • 記錄上一個執行的命令,支持undo()操作
  5. 工作流程:客戶端創建命令并綁定接收者,調用者通過命令間接操作接收者,實現了發送者與接收者的解耦。

命令模式的優缺點

優點

  • 實現了發送者與接收者的解耦,發送者無需知道接收者的具體實現
  • 容易擴展新命令,符合開放-封閉原則
  • 支持命令的排隊、日志記錄和撤銷操作
  • 可以組合多個命令形成復合命令(宏命令)

缺點

  • 可能導致系統中出現大量具體命令類,增加系統復雜度
  • 命令的撤銷/重做功能實現復雜,需要保存歷史狀態

適用場景

  • 當需要將請求發送者與接收者解耦時
  • 當需要支持命令的撤銷、重做操作時
  • 當需要將多個命令組合成復合命令時
  • 當需要實現請求的排隊執行或日志記錄時

常見應用:

  • 圖形界面中的菜單操作、按鈕點擊
  • 事務處理(支持提交和回滾)
  • 任務調度系統(命令排隊執行)
  • 遙控器、游戲手柄等設備的操作抽象

命令模式通過將操作封裝為對象,為系統帶來了更大的靈活性和可擴展性,特別適合需要支持撤銷、日志、事務等功能的場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93400.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web攻防-大模型應用LLM搭建接入第三方內容喂養AI插件安全WiKI庫技術賦能

知識點&#xff1a; 1、WEB攻防-LLM搭建-AI喂養&安全知識WIKI庫 演示案例&#xff1a;WEB攻防-LLM搭建-AI喂養&安全知識WIKI庫 使用參考 https://docs.web2gpt.ai/ https://mp.weixin.qq.com/s/qqTOW5Kg1v0uxdSpbfriaA 0、服務器環境&#xff1a;阿里云 Ubuntu22.04 …

圖片拼接-動手學計算機視覺8

前言圖片拼接&#xff08;image stitching&#xff09;就是將統一場景的不同拍攝出的圖片拼接到一起&#xff0c;如圖所示就是拼接全景圖&#xff0c;是圖片拼接的應用之一&#xff0c;手機拍照都有全景拍攝功能仔細觀察全景圖&#xff0c;尋找它們相似性&#xff0c;圖8-2的全…

Web第二次作業

作業一&#xff1a;學校官網1.1學校官網代碼如下&#xff1a;?<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

【CV 目標檢測】②R-CNN模型

二、R-CNN網絡基礎 2.R-CNN模型 2014年提出R-CNN&#xff01;網絡&#xff0c;該網絡不再使用暴力窮舉的方法&#xff0c;而是使用候選區域方法&#xff08;region proposal method&#xff09;創建目標檢測的區域來完成目標檢測的任務&#xff0c;R-CNN是以深度神經網絡為基礎…

STM32L051C8與STM32L151C8的主要區別

STM32L051C8與STM32L151C8 有什么區別&#xff1f; LPTIM 有什么特點,為什么STM32L151C8沒有LPTIM,而STM32L051C8有1個? 1. STM32L051C8與STM32L151C8的主要區別 STM32L051C8STM32L151C8內核Cortex-M0Cortex-M3主頻32MHz32MHz閃存/ SRAM64KB/8KB64KB/16KB工作電壓1.65V-3.6V…

【軟考中級網絡工程師】知識點之網關協議深度剖析

目錄一、網關協議基礎探秘1.1 網關協議概念1.2 網關協議作用1.3 網關協議分類總覽二、內部網關協議&#xff08;IGP&#xff09;深度解析2.1 距離矢量協議2.2 鏈路狀態協議2.3 混合型協議三、外部網關協議&#xff08;EGP&#xff09;探秘3.1 BGP 協議詳解3.2 BGP 協議的關鍵特…

JavaScript 中 call、apply 和 bind 方法的區別與使用

一、核心作用與基礎概念這三個方法都用于顯式改變函數執行時的 this 指向&#xff0c;解決 JavaScript 中函數上下文動態綁定的問題。1.call()立即執行函數&#xff0c;第一個參數為 this 指向對象&#xff0c;后續參數為逗號分隔的參數列表語法&#xff1a;func.call(thisArg,…

【Android】適配器與外部事件的交互

三三要成為安卓糕手 引入&#xff1a;在上一篇文章中我們完成了新聞展示頁面多布局案例的展示&#xff0c;感悟頗多&#xff0c;本篇文章&#xff0c;繼續去開發一些新的功能 一&#xff1a;關閉廣告 所有的view都可以和我們的用戶做交互&#xff0c;循環視圖中也給我們提供了相…

MySQL的分析查詢語句(EXPLAIN):

目錄 基本語法&#xff1a; 各個字段的含義&#xff1a; id&#xff1a; select_type&#xff1a; table&#xff1a; partitions&#xff1a; type&#xff1a; possible_keys&#xff1a; key&#xff1a; key_len&#xff1a; ref&#xff1a; row&#xff1a; …

C++ #if

在 C 中&#xff0c;#if 是 預處理器指令&#xff08;Preprocessor Directive&#xff09;&#xff0c;用于 條件編譯&#xff0c;即在編譯階段根據條件決定是否包含某段代碼。它通常與 #define、#ifdef、#ifndef、#else 和 #endif 配合使用。基本語法#if 條件表達式// 如果條件…

方案 | 動車底部零部件檢測實時流水線檢測算法改進

項目背景隨著我國高速鐵路運營里程突破4.5萬公里&#xff0c;動車組日均開行超過8000列次&#xff0c;傳統人工巡檢方式已無法滿足密集運行下的安全檢測需求。車底關鍵部件如制動系統、懸掛裝置、牽引電機等長期承受高強度振動和沖擊&#xff0c;易產生疲勞裂紋、螺栓松動、部件…

企業收款統計:驅動業務決策的核心引擎設計開發——仙盟創夢IDE

代碼完整代碼<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>黑金風格職員統計</title><style>/* 頁面基礎樣式 - 黑金風格 */body {font-family: Segoe UI, Tahoma, Geneva, Verdana, …

CIAIE 2025上海汽車內外飾展觀察:從美學到功能的產業躍遷

在智能化、電動化浪潮推動下&#xff0c;汽車產業的市場格局、技術路線、供應鏈結構與用戶體驗正被系統性重塑。汽車感知空間核心的“內外飾件”&#xff0c;正從原本的結構性、功能性部件&#xff0c;逐步躍升為智能化、情感化和差異化體驗的重要承載載體&#xff0c;開啟了從…

Spring IOC容器在Web環境中的啟動奧秘:深入源碼解析

一、為何需要關注IOC容器啟動&#xff1f;在Java Web開發中&#xff0c;Spring MVC框架的基石正是IOC容器。但你是否思考過&#xff1a;獨立的IOC模塊如何與Tomcat等Servlet容器協同工作&#xff1f; 其啟動過程與Web容器的生命周期深度綁定&#xff0c;這是構建穩定Spring應用…

前端JS處理時間,適用于聊天、操作記錄等(包含剛剛、x分鐘前、x小時前、x天前)

export default {// 首頁時間轉化formatDate(val) {var nowDate new Date()var oldDate new Date(val)const Y oldDate.getFullYear()const M oldDate.getMonth() 1const D oldDate.getDate()var diff nowDate.getTime() - oldDate.getTime()var minutes Math.floor(di…

C#---StopWatch類

老方法&#xff0c;想要全面了解和學習一個類必先看文檔 微軟文檔 1.StopWatch 提供一組方法和屬性&#xff0c;可用來測量運行時間。 1.1 屬性和方法 屬性&#xff1a; 方法&#xff1a; 1.2 使用 using System.Diagnostics;namespace Study04_反射專題 {internal cla…

3DTiles轉OSGB格式逆向轉換方法研究

一、概述 在傾斜攝影的應用領域中&#xff0c;3DTiles與OSGB格式的互轉是常見的技術需求。作為專業的GIS處理平臺&#xff0c;GISBox憑借其先進的傾斜攝影反切功能&#xff0c;為用戶提供了高效、穩定的跨格式數據轉換解決方案。 二、3DTiles轉OSGB的意義 保留原始幾何與紋理…

【門診進銷存出入庫管理系統】佳易王醫療器械零售進銷存軟件:門診進銷存怎么操作?系統實操教程 #醫藥系統進銷存

前言&#xff1a; &#xff08;一&#xff09;試用版獲取方式 資源下載路徑&#xff1a;進入博主頭像主頁第一篇文章末尾&#xff0c;點擊卡片按鈕&#xff1b;或訪問左上角博客主頁&#xff0c;通過右側按鈕獲取詳細資料。 說明&#xff1a;下載文件為壓縮包&#xff0c;使用…

華為交換機配置文件的相關命令和用法

文章目錄一、基本配置命令一、基本配置命令 1、查看當前運行的配置文件 <Huawei>display current-configuration2、配置文件保存 <Huawei>save <Huawei>save vrpcfg-20250623.zip #保存為指定文件名3、查看保存的配置 <Huawei>display saved-configu…

【汽車標定數據】動態優先級線程池在異步多文件解析中的應用

目錄 一、需求背景 項目背景&#xff1a;電控數據管理系統優化 優化方案&#xff1a;引入OLAP數據庫和動態線程池 線程池性能急需解決的問題 資源過載與閑置的平衡&#xff1a; 優先級處理與公平性&#xff1a; 任務類型適配性&#xff1a; 二、線程池介紹 2.1、線程池…