掌握設計模式--命令模式

命令模式(Command Pattern)

命令模式(Command Pattern)是一種行為型設計模式,它將請求(命令)封裝成對象,從而使您能夠參數化客戶端(調用者)使用不同的請求、隊列請求或者日志請求,甚至支持可撤銷的操作。

核心思想是?將請求封裝成對象,從而使得調用者與接收者解耦,同時支持請求的存儲、撤銷、重做和排隊執行。

主要組成部分

  1. Command(命令接口):通常是一個接口,定義一個執行命令的?execute()?方法。

  2. ConcreteCommand(具體命令):實現命令接口,并定義執行該命令的具體操作,通常將請求的接收者(Receiver)和操作綁定在一起。

  3. Client(客戶端):創建一個具體命令對象并設置其接收者(Receiver)。

  4. Invoker(調用者):請求命令的執行。通常在用戶操作時,會調用?execute()?方法。

  5. Receiver(接收者):知道如何實施與執行一個請求相關的操作,實際的業務邏輯通常由此類執行。

案例實現

一個?圖形編輯器,用戶可以執行對圖形的操作(如繪制、擦除等),并能夠撤銷這些操作。

案例類圖

image

命令調用者類依賴于命令接口,命令接口下的具體命令類操作實際的業務邏輯

Command接口

public interface Command {void execute();void undo();
}

繪制圖形命令

// ConcreteCommand - 繪制圖形命令
public class DrawShapeCommand implements Command {private Shape shape;public DrawShapeCommand(Shape shape) {this.shape = shape;}@Overridepublic void execute() {shape.draw();}@Overridepublic void undo() {shape.erase();}
}// ConcreteCommand - 刪除圖形命令
class EraseShapeCommand implements Command {private Shape shape;public EraseShapeCommand(Shape shape) {this.shape = shape;}@Overridepublic void execute() {shape.erase();}@Overridepublic void undo() {shape.draw();}
}

接受者--抽象圖形類

public abstract class Shape {protected String name;public abstract void draw();public abstract void erase();
}

接受者--具體圖形類

public class Circle extends Shape {public Circle() {this.name = "Circle";}@Overridepublic void draw() {System.out.println("繪制圖形 " + name);}@Overridepublic void erase() {System.out.println("擦除圖形 " + name);}
}class Rectangle extends Shape {public Rectangle() {this.name = "Rectangle";}@Overridepublic void draw() {System.out.println("繪制圖形 " + name);}@Overridepublic void erase() {System.out.println("擦除圖形 " + name);}
}

命令調用者

public class CommandInvoker {private Stack<Command> commandHistory = new Stack<>();public void executeCommand(Command command) {command.execute();commandHistory.push(command);}public void undo() {if (!commandHistory.isEmpty()) {Command lastCommand = commandHistory.pop();lastCommand.undo();} else {System.out.println("No commands to undo.");}}
}

測試代碼

public class CommandDemo {public static void main(String[] args) {// 創建圖形Shape circle = new Circle();Shape rectangle = new Rectangle();// 創建命令Command drawCircleCommand = new DrawShapeCommand(circle);Command drawRectangleCommand = new DrawShapeCommand(rectangle);Command eraseCircleCommand = new EraseShapeCommand(circle);Command eraseRectangleCommand = new EraseShapeCommand(rectangle);// 創建命令調用者CommandInvoker invoker = new CommandInvoker();// 執行命令invoker.executeCommand(drawCircleCommand);  // 繪制圓形invoker.executeCommand(drawRectangleCommand);  // 繪制矩形invoker.executeCommand(eraseCircleCommand);  // 刪除圓形invoker.executeCommand(eraseRectangleCommand);  // 刪除矩形// 撤銷操作invoker.undo();  // 撤銷刪除矩形invoker.undo();  // 撤銷刪除圓形invoker.undo();  // 撤銷繪制矩形invoker.undo();  // 撤銷繪制圓形invoker.undo();}
}

測試結果

繪制圖形 Circle

繪制圖形 Rectangle

擦除圖形 Circle

擦除圖形 Rectangle

繪制圖形 Rectangle

繪制圖形 Circle

擦除圖形 Rectangle

擦除圖形 Circle

No commands to undo.

優缺點和適用場景

優點:

  1. 解耦請求者和接收者:請求者(客戶端)不需要知道接收者的具體實現,只需要知道命令接口。

  2. 支持撤銷操作:可以將命令對象設計為支持撤銷的操作,使得某些操作能夠撤回。

  3. 可以將命令參數化:命令可以作為參數傳遞,或被存儲起來,支持批量操作。

  4. 擴展性好:增加新的命令時,不需要改變現有代碼,只需要新增具體命令類。

缺點:

  1. 增加類的數量:每個具體命令類都需要創建一個類,可能導致類的數量增多。

  2. 實現復雜度:如果系統中的命令非常多,可能導致命令類實現過于復雜。

命令模式在 GUI 程序、事務管理、隊列任務等場景中非常常見。

適用場景

  • 需要解耦請求者和接收者。

  • 需要撤銷、重做操作。

  • 需要存儲請求、支持隊列、日志功能。

  • 需要動態選擇操作或擴展操作。

  • 需要將多個操作封裝為一個命令。

  • 需要管理跨平臺或多設備的操作。

總結

命令模式的核心關注點是將請求封裝成對象,從而使得請求的發送者(調用者)和接收者(執行者)解耦。命令模式通過把請求封裝成命令對象,使得你可以在不改變請求者的情況下改變請求的執行方式、順序或者操作對象。

  • 行為封裝:命令模式將請求、操作或事務封裝為命令對象,這些對象可以被請求者調用。請求者不關心具體操作的執行方式,只需要調用命令對象的執行方法即可。

  • 請求者和執行者解耦:通過引入命令對象,調用者和被調用者的關系被解耦,調用者不需要知道如何執行操作,也不需要知道具體的操作是什么,只需要發出命令請求。

文章轉載自:淵渟岳

原文鏈接:掌握設計模式--命令模式 - 淵渟岳 - 博客園

體驗地址:JNPF快速開發平臺

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

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

相關文章

STM32之beep、多文件、延遲、按鍵以及呼吸燈

一、Beep控制 原理圖分析&#xff1a; 蜂鳴器三極管控制引腳對應 MCU PB8。當前蜂鳴器對應的電路中&#xff0c;三極管是 NPN 三極管&#xff0c;當前【基極】存在小電流&#xff0c;當前三極管導通。要求對應 PB8 引腳對外輸出電壓 / 電流。當前 PB8 輸出高電平&#xff0c;當…

C++的struct里面可以放函數,討論一下C++和C關于struct的使用區別

我們來看一個C代碼下面的struct結構體: struct UserValue {float lx;float ly;float rx;float ry;float L2;// 【構造函數】UserValue() {setZero();}// 【成員函數】void setZero() {lx 0;ly 0;rx 0;ry 0;L2 0;} };在這篇文章中&#xff0c;我們將來詳細解釋一下為什么 U…

【Kubernetes知識點】資源配額與訪問控制

目錄 1.解釋ResourceQuota的作用。 2.解釋Service Account的用途。 3.詳細解釋Role和ClusterRole。 4.什么是K8s的NetworkPolicy&#xff1f; 5.詳細描述在K8s中如何控制跨Namespace的Pod訪問&#xff1f; 1.解釋ResourceQuota的作用。 ResourceQuota&#xff08;資源配額…

在SAP Query中添加雙擊事件

在SAP系統中&#xff0c;SAP Query是一個強大的工具&#xff0c;允許用戶自定義報告以滿足特定的數據查詢需求。它提供了靈活的報表設計功能&#xff0c;使非編程背景的用戶也能創建和修改查詢。在某些情況下&#xff0c;我們可能希望在查詢結果上添加交互性&#xff0c;比如通…

c++:MFC中sqlite3的使用(附實際案例)

MFC中sqlite3的使用sqlite3介紹sqlite3安裝常用API函數操作流程接口函數執行sql語句函數回調函數MFC中案例實踐控制臺實踐sqlite3介紹 SQLite 是一個軟件庫&#xff0c;實現了自給自足的、無服務器的、零配置的、事務性的 SQL 數據庫引擎。SQLite 是在世界上最廣泛部署的 SQL …

LeetCode第1019題 - 鏈表中的下一個更大節點

題目 解答 class Solution {Stack<Integer> stack new Stack<>();List<Integer> values new LinkedList<>();public int[] nextLargerNodes(ListNode head) {nextLargerNodes2(head);return values.stream().mapToInt(x -> x).toArray();}publi…

STM32 硬件I2C讀寫MPU6050

本文代碼基于 STM32 單片機&#xff0c;通過 I2C 總線驅動 MPU6050 六軸傳感器&#xff08;集成加速度計與陀螺儀&#xff09;&#xff0c;實現傳感器初始化、ID 讀取、原始數據采集&#xff0c;并借助 OLED 顯示屏實時展示加速度&#xff08;AccX、AccY、AccZ&#xff09;與角…

倍福下的EC-A10020-P2-24電機調試說明

今天調試EC-A10020-P2-24電機&#xff0c;采用力位混合控制指令進行控制&#xff0c;無前饋力矩&#xff0c;只調節Kp和Kd,跟蹤紅色軌跡&#xff08;正弦信號&#xff1a;幅值10&#xff0c;頻率0.5Hz&#xff09;&#xff0c;結果顯示Kp 180, Kd 40&#xff0c;實際上Kp進一步…

SQL注入1----(sql注入原理)

一.前言前面我們講解了一下信息收集&#xff0c;本章節我們來講解一下sql注入的基本原理&#xff0c;我們拿之前搭建的測試網站pikachu來測試&#xff0c;對應工具包也已經放在了工具里面&#xff0c;大家可以自行去下載。SQL注入攻擊漏洞的原因&#xff0c;是由于程序員在編寫…

C++智能指針詳解:用法與實踐指南

C智能指針詳解&#xff1a;用法與實踐指南 在C編程中&#xff0c;動態內存管理始終是開發者面臨的重要挑戰。手動分配和釋放內存不僅繁瑣&#xff0c;還容易因疏忽導致內存泄漏、懸垂指針等問題。為解決這些痛點&#xff0c;C標準庫引入了智能指針&#xff08;Smart Pointers&a…

fastdds qos:DurabilityQosPolicy

假如DataWriter先起來&#xff0c;并且已經寫了一些數據&#xff0c;之后有新的DataReader起來&#xff0c;那么新起來的DataReader能不能接收到它啟動之前&#xff0c;DataWriter發布的數據呢。DurabilityQosPolicy用來做這種控制。VOLATILE_DURABILITY_QOS&#xff1a;易失的…

【讀代碼】SQLBot:開源自然語言轉SQL智能助手原理與實踐

一、項目簡介 SQLBot 是 DataEase 團隊開源的自然語言轉 SQL 智能助手,致力于讓非技術用戶也能通過自然語言與數據庫對話,自動生成 SQL 查詢,實現自助數據分析、智能BI問答、報表生成等場景。SQLBot 結合了大語言模型(LLM)、數據庫元數據解析、SQL解析與執行等多項技術,…

開題報告被退回?用《基于大數據的慢性腎病數據可視化分析系統》的Hadoop技術,一次通過不是夢

&#x1f496;&#x1f496;作者&#xff1a;計算機編程小咖 &#x1f499;&#x1f499;個人簡介&#xff1a;曾長期從事計算機專業培訓教學&#xff0c;本人也熱愛上課教學&#xff0c;語言擅長Java、微信小程序、Python、Golang、安卓Android等&#xff0c;開發項目包括大數…

HEVC(H.265)與HVC1的關系及區別

HEVC&#xff08;H.265&#xff09;與HVC1的關系及區別可歸納如下&#xff1a;一、技術定義差異?HEVC&#xff08;H.265&#xff09;?國際標準化組織制定的通用視頻編碼標準&#xff0c;由ITU-T和ISO/IEC聯合開發?1支持8K分辨率&#xff0c;壓縮效率較H.264提升約50%?1?HV…

Java獲取被nginx代理的emqx客戶端真實ip

Java獲取被nginx代理的emqx客戶端真實ip 契機 ? 使用nginx作為負載均衡&#xff08;Load Balancing&#xff09;的時候&#xff0c;發現真實ip無法獲取。幾經折騰終于拿到真實ip&#xff0c;又發現被代理的端口又無法使用非代理模式連接&#xff0c;由于之前暴露的docker端口有…

Jenkins自動化部署服務到Kubernetes環境

在現代軟件開發中,持續集成和持續部署(CI/CD)已成為提高開發效率和軟件質量的關鍵實踐。本文將介紹如何使用Jenkins自動化部署服務到Kubernetes環境,并重點介紹Maven與私服的配置。 環境準備 在開始之前,請確保您已準備好以下環境: Jenkins服務器 Kubernetes集群 Docker鏡…

OpenAI重新開源!gpt-oss-20b適配昇騰并上線魔樂社區

2025年8月5日&#xff0c;OpenAI發布了兩款全新的開源權重語言模型&#xff0c;均為混合專家&#xff08;MoE&#xff09;架構&#xff0c;其規模設計可在消費級GPU和云端的多種硬件上高效運行。這些模型采用 Apache 2.0 許可協議&#xff0c;因此可用于蒸餾到其他推理模型中、…

SpringCloud入門(簡潔明了)

目錄 一.創建微服務項目 (一)環境準備 (二)項目結構圖 (三)流程 二. Nacos (一)注冊中心 1.服務注冊 2.服務發現 3.編寫微服務API 4.遠程調用基本實現 5.負載均衡 6.LoadBalanced注解式注解均衡 7.注冊中心宕機&#xff0c;遠程調用還能成功嗎 (二)配置中心 1.基…

集成算法學習筆記

一、集成算法簡介1. 核心思想類比“多個專家綜合判斷優于單個專家”&#xff0c;通過構建并結合多個個體學習器&#xff0c;提升模型的泛化能力&#xff08;降低過擬合風險、提高預測準確性&#xff09;&#xff0c;完成復雜的學習任務。2. 個體學習器與結合模塊個體學習器&…

讓Chrome信任自簽名證書

讓Chrome信任自簽名證書&#xff08;Unix系列OS&#xff09; 背景 想在本地測試自己寫的基于HTTPS連接的Web應用&#xff0c;跑在3001端口。但使用Chrome瀏覽器訪問https://localhost:3001時顯示連接不安全。解決了但沒解決 使用mkcert一鍵創建證書&#xff1a; mkcert localho…