一、緒
上篇博客和大家分享了ffmpeg的編譯流程以及在AndroidStudio中集成。最近由于對ffmpeg的涉獵進展較慢,但是為了保持持續的狂暴之心,還是不能停止博客的更新。所以今天和大家分享一篇關于設計模式的內容。想必有些朋友看到設計模式幾字就有點精神錯亂,四肢麻木。哈哈,開個玩笑。我不會以單純描述設計模式來表達,這樣的博客隨便一搜很多。既然要說設計模式,畢竟缺少不了實戰的結合。
設計模式所帶來的效益是顯而易見的,23種設計模式體現了7種思想原則的守恒。大家最常用也最常聽說的 單例模式、原型模式、工廠模式、觀察者模式、建造者模式等等,同樣很多模式在Android源碼或者優秀的第三方開源庫中體驗的淋漓盡致。例如圖片加載庫,Glide,ImageLoader等等都以getInstance的方式使用了單例模式(雙重鎖檢查機制),Android源碼中AlertDialog使用build體現的建造者模式,Intent提供的clone原型模式,3.0后的屬性動畫插值器所體現的策略模式等等。本篇博客和大家分享一下狀態模式的定義以及實戰的使用。
狀態模式包含了三種定義:
(1)控制器
(2)抽象狀態或狀態接口
(3)具體狀態
怎么理解三者之間的關系呢?看下面展示圖:
上圖中,Context也就是控制器,即使用環境。State即為抽象狀態或狀態接口,Concrete
State
A,B即為具體的狀態實現,即狀態的具體行為。三者的關系顯而易見,在Context中提供setState以注入的方式來改變不同的狀態,體現不同狀態下的不同行為。
生活處處有設計模式。拿生活中的電視遙控器例子來說,在電視開機狀態下,遙控器可以控制音量,頻道切換等等,關機狀態下,對于電視的任何操作都不能進行。
此時,遙控器就對應于Context,State對應于電視的狀態,具體狀態對應于電視的開機、關機:
代碼描述如下:
(1)控制器接口,定義了兩種狀態的控制。
(2)具體控制器實現,實現狀態的切換。
(3)狀態接口
(4)開機狀態
(5)關機狀態
在我們平時開發的App應用中,肯定缺少不了登錄功能。App客戶端用戶狀態一般處于兩種狀態:
(1)登錄狀態
(2)注銷狀態(退出本次登錄)
兩種狀態下對應的App權限是不同的。例如,App中有商品的收藏、分享功能、加入購物車、支付功能等等。
用戶未登錄狀態時,可以進行商品分享操作,但不能對商品進行支付。反之,在用戶登錄后,即可進行商品收藏,商品下單支付等操作。
一般的做法是,會在每個功能模塊下,在業務處理前,例如在收藏功能模塊中,首先會對用戶的狀態進行判斷,如果用戶處于登錄狀態,處理收藏邏輯。否則跳轉到登錄界面,提示用戶登錄。如果功能模塊較少的情況下,還是可以接受。
考慮一種場景:用戶狀態切換不同的情況下,會有多種不同的狀態操作。此時需要在每個地方去做登錄狀態的判斷,顯而易見,這種方式非常繁瑣。在后面的工作中,如果還有與用戶狀態相關的操作,都需要去作重復的業務邏輯。
偽代碼:
了解到使用一般方式的弊端后,我們可以使用狀態模式來解決此問題。經過上面的分析,我們可以得到如下信息:
(1)用戶信息
(2)用戶狀態
(3)狀態行為
1.首先定義兩種狀態,兩種狀態對應了不同的行為方式:
2.狀態行為管理
3.Activity中使用
分析:
首先,定義了兩個具體的狀態類,并且實現了不用的行為處理方式。在登錄狀態下,可以進行收藏和支付。在未登錄狀態下,執行收藏和支付行為時,直接跳轉到登錄界面。
然后,為了不在Activity直接操作State的行為,避免了Activity和State耦合,引入了LoginContext單例類,以委托的方式通過狀態類來管理State的行為和狀態。
最后在Activity中通過LoginContext來執行具體操作:
首先默認狀態是未登錄狀態,此時點擊收藏和支付將跳轉到登錄界面。等點擊登錄后,狀態變為登錄狀態,點擊收藏或者支付將會進行具體我邏輯處理。
我們可以發現,整體代碼邏輯上變得如此清晰,去掉了重復冗余的判斷。
從上面的實戰中,不難發現。使用了狀態模式后,代碼邏輯變得清晰很多,減少了不必要的代碼耦合。同樣也可以發現,狀態模式基本可以應用在不同狀態下的同一行為的不同處理。減少了if else? 或者switch的狀態判斷以及邏輯耦合。但是也同樣增加了類和對象的個數。所以還需要我們在實際運用中根據需求來決策具體的使用方式。以上部分內容參考《Android源碼設計模式》。