Android 原始碼中的命令模式

PleaseCallMeCoder發表於2016-10-09

寫在前面

前面跟大家分享了裝飾者模式、觀察者模式、靜態工廠方法、工廠方法模式,今天跟大家分享下Android原始碼中的命令模式。

命令模式

定義

將一個請求封裝成一個物件,從而使你可用不同的請求對客戶進行引數化,對請求排隊或記錄請求日誌,以及支援可撤銷的操作。

使用場景

對於大多數請求——響應模式的功能,比較適合使用命令模式。

  • 系統需要將請求呼叫者和請求接收者解耦,使得呼叫者和接收者不直接互動。
  • 系統需要在不同的時間指定請求、將請求排隊(如:執行緒池+工作佇列)和執行請求。
  • 系統需要支援命令的撤銷(Undo)操作和恢復(Redo)操作(比如系統掛掉之後重啟做一些恢復操作,還有資料庫的事務等)。
  • 系統需要將一組操作組合在一起,即支援巨集命令。

結構

Android 原始碼中的命令模式

命令模式涉及到的角色:

  • 客戶角色(Client):Client可以建立具體的命令物件,並且設定命令物件的接收者。Tips:不能把Clinet理解為我們平常說的客戶端,這裡的Client是一個組裝命令物件和接受者物件的角色,或者你把它理解為一個裝配者。
  • 呼叫者角色(Invoker):負責呼叫命令物件執行請求,通常會持有命令物件(可以持有多個命令物件)。Invoker是Client真正觸發命令並要求命令執行相應操作的地方(使用命令物件的入口)。
  • 命令角色(Command):定義命令的介面,宣告具體命令類需要執行的方法。這是一個抽象角色。
  • 具體命令角色(ConcreteCommand):命令介面的具體實現物件,通常會持有接收者,並呼叫接收者的功能來完成命令要執行的操作。
  • 接收者角色(Receiver):Receiver是真正執行命令的物件。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。

實現

命令模式其實就是對命令進行封裝,將命令請求者和命令執行者的責任分離開來實現鬆耦合。 這裡我們通過一個餐廳點餐的例項來剖析一下命令模式:命令接收者Cook可以做各式各樣的菜,根據Waiter送過來的訂單來滿足顧客的需求,具體命令實現類PigCook執行做烤乳豬命令,DuckCook執行燒花鴨命令等等,Client負責組裝各個部分。

命令角色

命令接收者

具體命令角色

呼叫者角色

客戶角色

可是,為什麼要這麼複雜咧,我只是想點個菜而已嘛,直接這麼搞不就好了?

我們知道命令模式的一個優點是支援命令的撤銷(Undo)操作和恢復(Redo)操作,如果我們像上邊一樣呼叫,我們要想做撤銷是不是就不那麼方便了呢。同時還可以考慮下命令模式的其他幾個優點。

總結

  • 每一個命令都是一個操作:請求的一方發出請求,要求執行一個操作;接收的一方收到請求,並執行操作。
  • 命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的介面,更不必知道請求是怎麼被接收,以及操作是否被執行、何時被執行,以及是怎麼被執行的。
  • 命令模式使請求本身成為一個物件,這個物件和其他物件一樣可以被儲存和傳遞。
  • 命令模式的關鍵在於引入了抽象命令介面,且傳送者針對抽象命令介面程式設計,只有實現了抽象命令介面的具體命令才能與接收者相關聯。

Android原始碼中的命令模式

對於Android原始碼來說,Android底層邏輯對事件的轉發處理就用到了命令模式。Application Framework(應用程式框架層)中PackageManagerService類(包管理部分)也用到了命令模式。PackageManagerService是Android系統的Service之一,主要功能是實現對應用包的解析、管理、解除安裝等操作。我們來看下具體的結構。

Android 原始碼中的命令模式

HandlerParams是命令介面,即我們的Command角色。

具體的包的安裝、移動以及包大小的測量分別在3個具體子類InstallParams、MoveParams和MeasureParams中實現。

而PackageHandler是Handler的子類,用來負責包相關訊息的處理,不同的請求對應不同的命令物件,然後通過命令物件來執行具體操作。

關於Receiver

通過接觸Android原始碼或者其他的一些原始碼,我們知道有些地方是沒有命令接收者(Receiver)這個角色的,這是為什麼呢?

個人認為,有的命令接收實現非常簡,可以直接用少量的程式碼來實現,沒有必要再增加類的數量。

參考連結:

https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/command/lijunhuayc

http://blog.csdn.net/wwh578867817/article/details/51533263

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

Android 原始碼中的命令模式 Android 原始碼中的命令模式

相關文章