設計模式-command模式
定義命令模式
命令模式將“請求”封裝成物件,以便使用不同的請求、佇列或者日誌來引數化其他物件。命令模式也支援可撤銷的操作。命令物件將動作和接收者包進物件中。
應用場景
在面向物件的軟體設計中,經常會遇到一個(或一系列)物件,物件本身的資料儲存與物件的操作耦合在一起。例如一個物件有add(),edit(),delete()方法,這樣物件支援的方法很難擴充套件,如果需要加入update()就必須修改程式碼,客戶端與物件也是緊耦合的。命令模式是將一類物件的功能(行為,功能)抽象成一個命令物件,客戶端在使用的時候,只與該命令物件打交道,而不用與物件打交道,分離命令的請求者和命令的執行者,降低了耦合性,可以使用不同的請求對客戶進行引數化提高了程式設計的靈活性命令模式的類圖
下面是Head First設計模式上面定義命令模式的類圖 遙控器問題:有一個附著多組開關按鈕的遙控器,帶有可程式設計插槽,每個都可以指定到一個不同的家電裝置;有很多廠商開發的各種家電裝置控制類;希望建立一組API,讓每個插槽控制一個或一組裝置。下面是Head First設計模式上實現遙控器問題的類圖遙控器問題:
可以把遙控器的按鈕看做是一個命令,按下命令的時候不需要知道命令是怎麼執行的,我們可以將遙控器每個按鍵看做是一個命令物件,實現的時候用陣列來表示遙控器的按鈕位置,然後為陣列賦值具體對應的命令物件
撤銷操作的實現class Light { String location = ""; public Light(String location) { this.location = location; } public void on() { System.out.println(location + " light is on"); } public void off() { System.out.println(location + " light is off"); } } //命令類實現 class LivingroomLightOffCommand implements Command { Light light; public LivingroomLightOffCommand(Light light) { this.light = light; } public void execute() { light.off(); } } class LivingroomLightOnCommand implements Command { Light light; public LivingroomLightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } } class Stereo { String location; public Stereo(String location) { this.location = location; } public void on() { System.out.println(location + " stereo is on"); } public void off() { System.out.println(location + " stereo is off"); } public void setCD() { System.out.println(location + " stereo is set for CD input"); } public void setDVD() { System.out.println(location + " stereo is set for DVD input"); } public void setRadio() { System.out.println(location + " stereo is set for Radio"); } public void setVolume(int volume) { // code to set the volume // valid range: 1-11 (after all 11 is better than 10, right?) System.out.println(location + " Stereo volume set to " + volume); } } class StereoOffCommand implements Command { Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.off(); } } class StereoOnWithCDCommand implements Command { Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume(11); } } class NoCommand implements Command { public void execute() { } public void undo() { } } // This is the invoker // //invoker相當於訂單。它可以呼叫execute方法 class RemoteControl { Command[] onCommands; Command[] offCommands; public RemoteControl() { //在構造器例項化並初始化兩個開與關的陣列 onCommands = new Command[7]; offCommands = new Command[7]; Command noCommand = new NoCommand(); for (int i = 0; i < 7; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; //在構造器中將每個插槽都預先指定成noCommand物件,以便確定每個插槽永遠都有命令物件 } } //將命令記錄在開關陣列中對應的插槽位置插槽 public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } //按下按鍵 呼叫execute public void onButtonWasPushed(int slot) { onCommands[slot].execute(); } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); } public String toString() { StringBuffer stringBuff = new StringBuffer(); stringBuff.append("\n------ Remote Control -------\n"); for (int i = 0; i < onCommands.length; i++) { stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + " " + offCommands[i].getClass().getName() + "\n"); } return stringBuff.toString(); } } //測試 public class RemoteLoader { public static void main(String[] args) { RemoteControl remoteControl = new RemoteControl(); Light livingRoomLight = new Light("Living Room"); Light kitchenLight = new Light("Kitchen"); CeilingFan ceilingFan= new CeilingFan("Living Room"); GarageDoor garageDoor = new GarageDoor(""); Stereo stereo = new Stereo("Living Room"); LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight); LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight); LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight); LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight); StereoOnWithCDCommand stereoOnWithCD = new StereoOnWithCDCommand(stereo); StereoOffCommand stereoOff = new StereoOffCommand(stereo); remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); remoteControl.setCommand(1, stereoOnWithCD, stereoOff); System.out.println(remoteControl) remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); remoteControl.onButtonWasPushed(1); remoteControl.offButtonWasPushed(1); } }
新加入undo方法 然後每個具體的命令類都實現這個方法:undo方法中呼叫的操作和execute()方法中的操作相反,比如on的反面是off。
遙控器類也要做一些修改:加入新的例項變數記錄上一個操作,當按下撤銷按鈕,就呼叫該例項變數的undo()方法。
如果撤銷到某一個狀態需要記錄一些變數值,則在execute()方法中加入儲存操作前狀態數值的語句,然後在undo()的時候恢復。
例如將一個控制電風扇的命令加上undo方法
public class CeilingFanOffCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanOffCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.off(); } public void undo() { if (prevSpeed == CeilingFan.HIGH) { ceilingFan.high(); } else if (prevSpeed == CeilingFan.MEDIUM) { ceilingFan.medium(); } else if (prevSpeed == CeilingFan.LOW) { ceilingFan.low(); } else if (prevSpeed == CeilingFan.OFF) { ceilingFan.off(); } } }
實現Party模式
實現Party模式就是按下一個遙控器開關按鈕會有一系列的執行者j接收到命令按一定的次序執行操作。實現得方法是使用巨集命令,用命令陣列儲存一大堆命令,在execute()方法中用一個for迴圈遍歷這個陣列,依次執行陣列各個執行物件的execute
//實現命令陣列
class MacroCommand implements Command {
Command[] commands;
public MacroCommand(Command[] commands) {
this.commands = commands;
}
public void execute() {
for (int i = 0; i < commands.length; i++) {
commands[i].execute();
}
}
public void undo() {
for (int i = 0; i < commands.length; i++) {
commands[i].undo();
}
}
}
//使用巨集命令示例
Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
System.out.println(remoteControl);
System.out.println("--- Pushing Macro On---");
remoteControl.onButtonWasPushed(0);
System.out.println("--- Pushing Macro Off---");
remoteControl.offButtonWasPushed(0);
相關推薦
設計模式-command模式
定義命令模式 命令模式將“請求”封裝成物件,以便使用不同的請求、佇列或者日誌來引數化其他物件。命令模式也支援可撤銷的操作。命令物件將動作和接收者包進物件中。 應用場景 在面向物件的軟體設計中,經常會遇到一個(或一系列)物件,物件本身的資料儲存與物件的操作耦合在一
設計模式-命令模式(command pattern)
名稱:命令模式 說說:這其實和小時候我們傳紙條是一樣一樣的,一張紙條代表一條命令 動機: 適用性: 參與者: 結果:將一個請求封裝為一個物件 類圖: 說明:一個命令(請求)就是一個例項(命令物件 = 動作的執行者 + 要執行的行為),傳送一個命令就是傳遞一個命令引數。 d
設計模式-行為模式
a)結構:注:1)使多個物件都有機會處理請求,從而避免請求的傳送者和接收者之間耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理她為止。b)優點:i.降低耦合程度。每個物件僅需知道如何將請求往後轉發。(每個物件只需保留一個後繼的引用)ii.在職責分發方
設計模式-工廠模式(FactoryMethod)
我的github 對於一個Java應用來說,會存在很多的呼叫關係,比如物件A的方法呼叫物件B的方法,就說物件A依賴物件B. 常規的做法是在類A中例項化B物件,再進行使用.但是這裡存在一個問題,如果將來進行應用升級改進,不再使用B的方法而是使用物件C的方法.如
【python + 設計模式】command模式
command模式個人覺得主要的作用就是,將需要執行的action分離並封裝,完成對該類行為的一些類似於command的操作。 比如:執行記錄、統計、撤消、佇列等。 這種模式在python中沒有涉及到啥特殊操作。 """ *TL;DR80 Encapsulates all
設計模式之命令模式(Command)摘錄
single 而是 names 都得 結構 意圖 iterator nbsp 軟件 23種GOF設計模式一般分為三大類:創建型模式、結構型模式、行為模式。創建型模式抽象了實例化過程,它們幫助一個系統獨立於怎樣創建、組合和表示它的那些對象。一個類創建型模式使用繼承改變被實例
設計模式之命令模式 Command
sta clas ide class open cli private 2017年 命令模式 介紹 角色 使用場景 代碼實現 public interface Command { //這個方法是一個返回結果為空的方法 //實際項目中,可
c#設計模式系列:命令模式(Command Pattern)
為我 pattern 代碼 spa pro round 產生 技術分享 image 引言 命令模式,我感覺“命令”就是任務,執行了命令就完成了一個任務。或者說,命令是任務,我們再從這個名字上並不知道命令的發出者和接受者分別是誰,為什麽呢?因為我們並不關心他們是誰,發出命令
C#設計模式(15)——命令模式(Command Pattern)
兩個 學院 做的 text server trac handle 接受 color 一、前言 之前一直在忙於工作上的事情,關於設計模式系列一直沒更新,最近項目中發現,對於設計模式的了解是必不可少的,當然對於設計模式的應用那更是重要,可以說是否懂得應用設計模式在項目中是衡
【Python設計模式】06 觀察者模式-瞭解物件的情況
六、觀察者模式-瞭解物件的情況 這章可以討論行為型設計模式:觀察者設計模式 本章主題 行為型設計模式簡介 觀察者設計模式及其 UML圖 利用 Python3.x程式碼實現一個真實用例 鬆耦合的強大威力 常見問答 1. 行為型模式簡介
【Python設計模式】04 門面模式-與門面相適
四、門面模式-與門面相適 Python3.x 本章研究結構型設計模式:門面模式 本章主題 結構型設計模式概要 利用UML圖理解門面設計模式 Python3.x實現程式碼的真實用例 門面模式與最少知識原則 1. 理解結構型設計模式
Command模式(命令設計模式)
Command?? 把方法的呼叫用一個類的例項來承載,要管理工作的歷史記錄,建立這些方法執行的命令的集合,只需管理這些例項的集合即可,而且還可以隨時再次執行過去的命令,或是將多個過去的命令整合為一個新命令並執行。稱之為Command設計模式 那裡合適使用: Command有時也被稱為事件(event
重走Java設計模式——命令模式(Command Pattern)
命令模式 定義 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫物件尋找可以處理該命令的合適的物件,並把該命令傳給相應的物件,該物件執行命令。 命令模式設計角色
設計模式之命令模式(Command Pattern)
摘要 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫 介紹 意圖:將一個請求封裝成一個物件,從而使您可以用不同的請求對客戶進行引數化。 主要解決:在軟體系統中,行為請求者與行為實現者通常是一種緊
二十三種設計模式[14] - 命令模式(Command Pattern)
前言 命令模式,物件行為型模式的一種。它幫助我們將功能的呼叫者與實現者之間解耦(甚至完全解耦)。呼叫者與實現者之間並不是直接引用關係,呼叫者只需要知道如何傳送當前功能的請求即可,而不用關心該請求由誰在何時完成。
設計模式(Java)—Command模式
一個類在進行工作時會呼叫自己或是其他類的方法,雖然呼叫結果會反映在物件的狀態中,但是並不會留下工作的歷史紀錄。 這時,如果有一個類,用來表示進行這項工作的命令就會方便很多。每一項想做的工作就不再是方法的呼叫這種動態處理了,而是一個表示命令的類的例項,既可以用物來
設計模式-命令模式(Command)
命令模式:將一個請求封裝為一個物件,從而可用不同的請求對客戶進行引數化;對請求排隊或記錄日誌,以及支援可撤銷的操作,將”發出請求的物件”和”接收與執行這些請求的物件”分隔開來。 角色和職責: 1.Command: 宣告執行操作的介面 2.Concrete Co
設計模式之命令模式(Command Pattern)
命令模式定義 命令模式是一個高內聚的模式。Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requ
Java23種設計模式【15】----》命令模式(command)
專案中用到的不多 一、介紹 通過抽象一個新的類,對發的請求和命令快取處理後(記錄日誌,記錄操作前狀態),再轉發給命令的執行者; 例如:資料庫事物的底層就是命令模式 二、結構 三、開發中的場景 四、類圖 五、程式碼實現 1、真正的命令執行者(
Java設計模式之從[打飛機遊戲中的控制器]分析命令(Command)模式
首先請允許我囉嗦幾句。為什麼我們在軟體設計過程中強調設計模式?為軟體增加設計模式確實會增加一定的程式碼複雜程度,但是它的好處是無窮的。它可以使得軟體更加易於擴充套件而無需改變原始碼。“解耦”是設計模式中的一個關鍵詞。例如,對於某個物件obj,在呼叫obj.method(