1. 程式人生 > >設計模式之命令模式(一)

設計模式之命令模式(一)

在本次學習過程中,我們把封裝帶到一個全新的境界:把方法呼叫(method invocation)封裝起來。沒錯,通過封裝方法呼叫,我們可以把運算塊包裝成形。

所以呼叫此運算的物件不需要關心事情是如何進行的,只要知道如何使用包裝成形的方法來完成它就可以。通過封裝方法呼叫,也可以做一些很聰明的事情,例如記錄日誌,或者重複使用這些封裝來實現撤銷。讓我們開始吧

現在有一個使用者A,他們家有很多家電,在裝修的時候,他讓裝修公司把這些家電當成了一個整體,想要通過一個遙控器就能控制家裡的電燈、風扇、熱水器、音響裝置和其他的類似的可控制裝置,這樣的話就顯得很高大上。

所以呢,他讓每個廠商投提供了一組Java類,用來控制家電。手上又有一個遙控器,希望我們能夠建立一組控制遙控器的API,讓每個插槽都能控制一個或一組裝置,即通過一個遙控器就能控制所有家電,是不是很酷。

我們先來看下廠商給的類。

這個類確實不少呀,而且介面也各有差異。還有更麻煩的,隨著家電數量的增加,這樣的類還會越來越多。那麼,如何設計一個遙控器API就變得很有挑戰性了是吧。

所以,命令模式應運而生了。在我們的設計中,採用“命令模式”,利用命令物件,把請求(例如開啟電燈)封裝成一個特定物件(例如客廳電燈物件)。所以,如果對每個按鈕都儲存一個命令物件,那麼當按鈕被按下的時候,就可以請命令物件做相關的工作。遙控器並不需要知道工作內容是什麼,只要有個命令物件能和正確的物件溝通,把事情做好就可以了。這樣,遙控器和電燈物件都解耦了。

可能把遙控器換成餐廳點餐,大家會更容易理解。我在這裡簡單描述下:首先顧客到了餐廳,根據選單點了一部分菜,把選單給服務員;服務員拿到了訂單,就提交到櫃檯上,並向後廚喊了一聲“xx號桌xx訂單”來了;後廚根據選單進行配菜,燒菜。全稱服務員都不需要知道訂單具體內容是什麼,只要將桌上的客戶點的餐提供給後廚即可,這和我們的遙控器就是一個道理了。

第一個命令物件

實現命令介面

那我們就來建立我們的命令物件吧。首先,我們得讓所有的命令物件實現相同的包含一個方法的介面。在餐廳訂餐的例子上,就是建立訂單,我們在程式的世界裡,取名叫做execute()

public interface Command {
    public void execute();
}
實現一個開啟電燈的命令

現在,假設想實現一個開啟電燈的命令。根據之前看到的廠商提供的類,Light類有兩個方法,on和off。

// 這是一個命令,所以需要實現Command介面
public class LightOnCommand implements Command {
    Light light;

// 構造器傳入某個電燈,以便讓這個命令控制,然後記錄在例項變數中
    public LightOnCommand(Light light) {
        this.light = light;
    }

// 這個execute方法呼叫接收物件的on方法
    public void execute() {
        light.on();
    }

}

使用命令物件

現在,我們讓遙控器工作起來,先來點簡單的。假設遙控器只有一個按鈕和對應的插槽,可以控制一個裝置:

public class SimpleRemoteControl {
// 有一個插槽持有命令,而這個命令控制著一個裝置
    Command slot;
 
    public SimpleRemoteControl() {}
 
// 這個方法用來設定插槽控制的命令
    public void setCommand(Command command) {
        slot = command;
    }
 
// 當按下按鈕時,這個方法就會被呼叫,使得當前命令銜接插槽,並呼叫它的execute方法
    public void buttonWasPressed() {
        slot.execute();
    }
}

就這樣我們就能實現一個簡單的遙控器了。請看我們的測試

public class RemoteControlTest {
    public static void main(String[] args) {
    // 遙控器就是呼叫者,會傳入一個命令物件,可以用來發出請求
        SimpleRemoteControl remote = new SimpleRemoteControl();
    // 現在建立一個電燈物件,此物件也就是請求的接收者
        Light light = new Light();
    // 這裡建立一個命令,然後將接收者傳給它
        LightOnCommand lightOn = new LightOnCommand(light);
    
    // 把命令傳給呼叫者
        remote.setCommand(lightOn);
    // 模擬按下按鈕
        remote.buttonWasPressed();
    }
    
}

定義命令模式

經過訂餐流程的理解,以及剛才這個小練習,相信你也對命令模式內的類 和物件如何互動理解得很清楚了吧。那我們在這裡趁熱打鐵,定義一下命令模式。

命令模式將請求封裝成物件,以便使用不同的請求,佇列或者日誌來引數化其他物件。命令模式也支援可撤銷的操作。

仔細想想,我們知道有一個命令物件通過在特定接收者上繫結一組動作來封裝一個請求。要達到這一點,命令物件將動作和接收者包進物件中。這個物件只暴露出一個execute()方法,當此方法被呼叫的時候,接收者就會進行這些動作。從外面來看,其他物件不知道究竟哪個接收者進行了哪些動作,只知道如果呼叫execute()方法,請求的目的就能達到。

讓我們來看下命令模式的類圖:

好了,通過這個簡單的小練習,我們知道如何控制電燈的開關了。在前面廠商給的類中,還有好多方法,比如電風扇、吊燈、電視機、音響等等。控制單個我們已經能搞定了,那控制多個呢?是不是同理呢?還是你有更好的方式呢?小編想請你先動動你的小手,我們下次見分曉。

愛生活,愛學習,愛感悟,愛挨踢

相關推薦

設計模式問題集錦

是把 後繼 ogr data- 跟著 沒有 解釋器 space 基本實現 設計模式的主要資料是《大話設計模式》。第一階段先看看各種模式的基本概念。實現每一個模式下的樣例。然後在進行理解性的學習和掌握,靈活掌握各種模式的長處,知道某種模式適合那種狀態。如今,樣

Java設計模式總體簡介——簡單易懂

設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。使用設計模式是為了可重用程式碼、讓程式碼更容易被他人理解、保證程式碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使程式碼編制真正工程化,設計模式是

Javascript設計模式簡單工廠

建立型設計模式-簡單工廠模式 簡單工廠模式(Simple Factory):又稱之為靜態工廠模式,由一個工廠物件建立某一種產品物件類的例項。主要用來建立同一類物件。 多類單例項法 為了加深我們的理解,設定以下需求。假設一個大型超市賣各種東西,

設計模式命令模式

在本次學習過程中,我們把封裝帶到一個全新的境界:把方法呼叫(method invocation)封裝起來。沒錯,通過封裝方法呼叫,我們可以把運算塊包裝成形。 所以呼叫此運算的物件不需要關心事情是如何進行的,只要知道如何使用包裝成形的方法來完成它就可以。通過封裝方法呼叫,也可以做一些很聰明的事情,例如記錄日誌,

設計模式命令模式Command Pattern

摘要 命令模式(Command Pattern)是一種資料驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在物件中,並傳給呼叫物件。呼叫 介紹 意圖:將一個請求封裝成一個物件,從而使您可以用不同的請求對客戶進行引數化。 主要解決:在軟體系統中,行為請求者與行為實現者通常是一種緊

C++:設計模式命令模式例子

// 設計模式測試.cpp : 定義控制檯應用程式的入口點。 // 命令模式 #include "stdafx.h" #include <string> #include <iost

設計模式命令模式

上一次留給大家去做的實踐,不知道大家執行的怎麼樣了呢。 我們通過一個簡單的練習,完成了一個控制開關。那現在,我們打算將遙控器的每個插槽,對應到一個命令這樣就要遙控器變成“呼叫者”。當按下按鈕,相應命令物件的execute()方法就會被呼叫,其結果就是,接收者(例如電燈、風扇、音響)的動作被呼叫。 實現遙控器

設計模式命令模式

我回來啦!今天是週六,一看命令模式還有一個總結未完成,趕緊爬起來做做好。 就如上一篇所說的,如果擁有了一個遙控器,卻無法光憑按下一個按你,就同時能弄暗燈光、開啟音響和電視、設定到DVD,並讓熱水器開始加溫,那麼我要這個遙控器還有什麼意義呢? 使用巨集命令 根據比較高階的想法來看,就是我們需要製造一種新的命令,

《大話設計模式》——讀後感 8好菜每回味不同——建造者模式基礎案例1

ted builds src ret 分離 args 類圖 rec 方法 建造者模式:是將一個復雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。 建造者模式通常包括下面幾個角色: 1. builder:給出一個抽象接口,以規範產品對象的各個組成成分的

設計模式六大原則轉載

具體類 ima 傳遞參數 基礎上 比較 擁有 tex 至少 基類 關於設計模式的六大設計原則的資料網上很多,但是很多地方解釋地都太過於籠統化,我也找了很多資料來看,發現CSDN上有幾篇關於設計模式的六大原則講述的比較通俗易懂,因此轉載過來。   原作者博客鏈接:http:/

設計模式六大原則例子-- 介面隔離原則ISP例子

之前我們對設計模式的六大原則做了簡單歸納,這篇部落格是對介面隔離原則進行的舉例說明。 1介面隔離原則的意義 建立單一介面,不要建立龐大臃腫的介面,儘量細化介面,介面中的方法儘量少。也就是說,我們要為各個類建立專用的介面,而不要試圖去建立一個很龐大的介面供所有依賴它的類去呼叫。 在程式設計中,依賴幾個

設計模式——java版》

        一、設計模式簡介         1. 設計模式是一套被反覆使用、多數人知曉、經過分類編目的優秀程式碼設計經驗的總結。使用設計模式是為了重用程式碼,使程式碼更容易理解並保證程式碼的可靠性。 &

設計模式裝飾者Decorator模式

首先來看一個場景,如圖: 工人分為很多種類,比如電工,管道工等等,同時又有A公司的電工,B公司的電工,A公司的管道工,B公司的管道工等等,那麼當有M個工種和N個公司的時候,就會有 M * N 個子類,這個繼承體系就會變得很龐大和複雜。那麼如何簡化呢,那麼

深入理解計算機系統--數值儲存-CPU大端和小端模式詳解

大端與小端 在嵌入式開發中,大端(Big-endian)和小端(Little-endian)是一個很重要的概念。 MSB與LSB 最高有效位(MSB)指二進位制中最高值的位元。在16位元的數字音訊中,其第1個位元便對16bit的字的數值有最大的

基本設計模式學習筆記:常見的七種面向物件設計原則

0.概述      面向物件設計原則為支援可維護性複用而誕生,這些原則蘊含在很多設計模式中,他們是從許多設計方案中總結出來的指導性原則1.單一原則     一個類只負責一個功能領域中的相應職責,或者說:就一個類而言,應該只有一個引起它變化的原因。個人總結:將不同職責的方法放在

設計模式美學習:為何說要多用組合少用繼承?如何決定該用組合還是繼承?

在面向物件程式設計中,有一條非常經典的設計原則,那就是:組合優於繼承,多用組合少用繼承。為什麼不推薦使用繼承?組合相比繼承有哪些優勢?如何判斷該用組合還是繼承? 為什麼不推薦使用繼承? 繼承是面向物件的四大特性之一,用來表示類之間的 is-a 關係,可以解決程式碼複用的問題。雖然繼承有諸多作用,但繼承層次過深

設計模式美學習:業務開發常用的基於貧血模型的MVC架構違背OOP嗎?

我們都知道,很多業務系統都是基於 MVC 三層架構來開發的。實際上,更確切點講,這是一種基於貧血模型的 MVC 三層架構開發模式。 雖然這種開發模式已經成為標準的 Web 專案的開發模式,但它卻違反了面向物件程式設計風格,是一種徹徹底底的面向過程的程式設計風格,因此而被有些人稱為反模式(anti-patter

設計模式命令模式

能夠 ger 不同 exec cor del 需要 content ces 設計模式之命令模式 Feb 24, 2015 命令模式(Command)的定義是:用於將一個請求封裝成一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日誌,以及執行可撤銷的

設計模式命令模式(Command)摘錄

single 而是 names 都得 結構 意圖 iterator nbsp 軟件 23種GOF設計模式一般分為三大類:創建型模式、結構型模式、行為模式。創建型模式抽象了實例化過程,它們幫助一個系統獨立於怎樣創建、組合和表示它的那些對象。一個類創建型模式使用繼承改變被實例

CLR設計類型接口

定義 除法 文章 div 面向 display ron 意思 color 寫到這一節的時候,CLR設計類型就已經結束了,因為CLR要求的是有一定基礎的人看的,所以我們不是從基礎類型以及運算符開始的,文章從一開始就講的是深入面向對象編程,研究C#程序的