Android 設計模式

來源:互聯網
上載者:User

標籤:down   隊列   product   相關   深度   介面隔離   single   多線程   com   

簡單介紹

項目開發中發現問題、解決這個問題這個過程中會出現非常多問題,比方反覆出現、某個問題的遺留,這些問題的本質就是設計模式。

今天記錄設計模式的知識點。


內容

在java以及其它的物件導向設計模式中,類與類之間主要有6種關係。他們各自是:依賴、關聯、彙總、組合、繼承、實現。

它們的耦合度依次增強。

依賴關係:
對於兩個相對獨立的對象,當一個對象負責構造還有一個對象的執行個體,或者依賴還有一個對象的服務時,這兩個對象之間主要體現為依賴關係。
關聯關係:
分為單向關聯和雙向關聯。在java中。單向關聯表現為:類A其中使用了類B。其中類B是作為類A的成員變數。雙向關聯表現為:類A其中使用了類B作為成員變數;同一時候類B中也使用了類A作為成員變數。


彙總關係:
是關聯關係的一種,耦合度強於關聯,他們的代碼錶現是同樣的,僅僅是在語義上有所差別:關聯關係的對象間是相互獨立的,而彙總關係的對象之間存在著包容關係。他們之間是“總體-個體”的相互關係。


組合關係:
是一種耦合度更強的關聯關係。存在組合關係的類表示“總體-部分”的關聯關係。“總體”負責“部分”的生命週期。他們之間是共生共死的。並且“部分”單獨存在時沒有不論什麼意義。
繼承:
表示類與類(或者介面與介面)之間的父子關係。


實現:
表示一個類實現一個或多個介面的方法。



設計原則

要點 定義 描寫敘述
單一職責原則 不要存在多於一個導致類變更的原因。通俗的說,即一個類僅僅負責一項職責。

問題由來:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而須要改動類T時,有可能會導致原本執行正常的職責P2功能發生問題。



解決方式:遵循單一職責原則。分別建立兩個類T1、T2,使T1完畢職責P1功能,T2完畢職責P2功能。這樣。當改動類T1時,不會使職責P2發生問題風險;同理,當改動T2時,也不會使職責P1發生問題風險。

裡氏替換原則 定義1:假設對每個類型為 T1的對象 o1。都有類型為 T2 的對象o2,使得以 T1定義的全部程式 P 在全部的對象 o1 都代換成 o2 時,程式 P 的行為沒有發生變化。那麼類型 T2 是類型 T1 的子類型。
定義2:全部引用基類的地方必須能透明地使用其子類的對象。
問題由來:有一功能P1,由類A完畢。現須要將功能P1進行擴充。擴充後的功能為P,其中P由原有功能P1與新功能P2組成。

新功能P由類A的子類B來完畢,則子類B在完畢新功能P2的同一時候。有可能會導致原有功能P1發生問題。

解決方式:當使用繼承時,遵循裡氏替換原則。

類B繼承類A時,除加入新的方法完畢新增功能P2外。盡量不要重寫父類A的方法,也盡量不要重載父類A的方法。

依賴倒置原則 高層模組不應該依賴低層模組,二者都應該依賴其抽象。抽象不應該依賴細節;細節應該依賴抽象。 問題由來:類A直接依賴類B。假如要將類A改為依賴類C,則必須通過改動類A的代碼來達成。

這樣的情境下,類A通常是高層模組,負責複雜的商務邏輯;類B和類C是低層模組,負責基本的原子操作。假如改動類A,會給程式帶來不必要的風險。



解決方式:將類A改動為依賴介面I,類B和類C各自實現介面I,類A通過介面I間接與類B或者類C發生聯絡,則會大大減少改動類A的幾率。

介面隔離原則 client不應該依賴它不須要的介面;一個類對還有一個類的依賴應該建立在最小的介面上。 問題由來:類A通過介面I依賴類B,類C通過介面I依賴類D,假設介面I對於類A和類B來說不是最小介面。則類B和類D必須去實現他們不須要的方法。



解決方式:將臃腫的介面I拆分為獨立的幾個介面。類A和類C分別與他們須要的介面建立依賴關係。也就是採用介面隔離原則。

迪米特法則 一個對象應該對其它對象保持最少的瞭解。 問題由來:類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對還有一個類的影響也越大。



解決方式:盡量減少類與類之間的耦合。

開閉原則 一個軟體實體如類、模組和函數應該對擴充開放。對改動關閉。

問題由來:在軟體的生命週期內,由於變化、升級和維護等原因須要對軟體原有代碼進行改動時。可能會給舊代碼中引入錯誤,也可能會使我們不得不正確整個功能進行重構,並且須要原有代碼經過又一次測試。

解決方式:當軟體須要變化時,盡量通過擴充軟體實體的行為來實現變化。而不是通過改動已有的代碼來實現變化。
     

設計模式

要點 定義 描寫敘述
單例模式 確保一個類僅僅有一個執行個體,並且自行執行個體化並向整個系統提供這個執行個體。 單例模式注意事項:
僅僅能使用單例類提供的方法得到單例對象。不要使用反射,否則將會執行個體化一個新對象。不要做斷開單例類對象與類中靜態引用的危急操作。多線程使用單例使用共用資源時,注意安全執行緒問題。
Factory 方法模式 定義一個用於建立對象的介面,讓子類決定執行個體化哪一個類,Factory 方法使一個類的執行個體化延遲到其子類。 在Factory 方法模式中,核心的工廠類不再負責全部的對象的建立。而是將詳細建立的工作交給子類去做。

這個核心類則搖身一變,成為了一個抽象工廠角色,僅負責給出詳細工廠子類必須實現的介面。而不接觸哪一個類應當被執行個體化這樣的細節。

抽象原廠模式 為建立一組相關或相互依賴的對象提供一個介面,並且無需指定他們的詳細類。 在下面情況下,適用於Factory 方法模式:
(1) 當一個類不知道它所必須建立的對象的類的時候。
(2) 當一個類希望由它的子類來指定它所建立的對象的時候。


(3) 當類將建立對象的職責託付給多個協助子類中的某一個,並且你希望將哪一個協助子類是代理者這一資訊局部化的時候。

模版方法模式 定義一個操作中演算法的架構,而將一些步驟延遲到子類中。使得子類能夠不改變演算法的結構就可以重定義該演算法中的某些特定步驟。 子類能夠置換掉父類的可變部分。可是子類卻不能夠改變模板方法所代表的頂級邏輯。
  每當定義一個新的子類時,不要依照控制流程程的思路去想,而應當依照“責任”的思路去想。換言之,應當考慮哪些操作是必須置換掉的,哪些操作是能夠置換掉的。以及哪些操作是不能夠置換掉的。使用模板模式能夠使這些責任變得清晰。

建造者模式 將一個複雜物件的構建與它的表示分離,使得同樣的構建過程能夠建立不同的表示。 與抽象工廠的差別:在建造者模式裡,有個指導者,由指導者來管理建造者,使用者是與指導者聯絡的,指導者聯絡建造者最後得到產品。

即建造模式能夠強制實行一種分步驟進行的建造過程。


  建造模式是將複雜的內部建立封裝在內部。對於外部調用的人來說,僅僅須要傳入建造者和建造工具。對於內部是怎樣建造成成品的,調用者無需關心。
在Java的應用中JavaMail使用到了該模式。

代理模式 為其它對象提供一種代理以控制對這個對象的訪問。 所謂代理,就是一個人或者機構代表還有一個人或者機構採取行動。

在一些情況下。一個客戶不想或者不能夠直接引用一個對象。而代理對象能夠在client和目標對象之間起到中介的作用。

原型模式 用原型執行個體指定建立對象的種類,並通過拷貝這些原型建立新的對象。

原型模式要求對象實現一個能夠“複製”自身的介面,這樣就能夠通過複製一個執行個體對象本身來建立一個新的執行個體。這樣一來,通過原型執行個體建立新的對象,就不再須要關心這個執行個體本身的類型。僅僅要實現了複製自身的方法,就能夠通過這種方法來擷取新的對象,而無須再去通過new來建立。
在Java語言裡深度複製一個對象。經常能夠先使對象實現Serializable介面,然後把對象(實際上僅僅是對象的拷貝)寫到一個流裡(序列化),再從流裡讀回來(還原序列化),便能夠重建對象。

原型模式的長處
  原型模式同意在執行時動態改變詳細的實作類別型。

原型模式能夠在執行期間,由客戶來注冊符合原型介面的實作類別型,也能夠動態地改變詳細的實作類別型。看起來介面沒有不論什麼變化,但事實上執行的已經是另外一個類執行個體了。

由於複製一個原型就相似於執行個體化一個類。



原型模式的缺點
  原型模式最基本的缺點是每個類都必須配備一個複製方法。配備複製方法須要對類的功能進行通盤考慮,這對於全新的類來說不是非常難。而對於已經有的類不一定非常easy,特別是當一個類引用不支援序列化的間接對象,或者引用含有迴圈結構的時候。

中介者模式 用一個中介者對象封裝一系列的對象互動。中介者使各對象不須要顯示地相互作用。從而使耦合鬆散,並且能夠獨立地改變它們之間的互動。

中介者模式的長處
適當地使用中介者模式能夠避免同事類之間的過度耦合,使得各同事類之間能夠相對獨立地使用。
使用中介者模式能夠將對象間一對多的關聯轉變為一對一的關聯。使對象間的關係易於理解和維護。
使用中介者模式能夠將對象的行為和協作進行抽象,能夠比較靈活的處理對象間的相互作用。

適用情境
       在物件導向編程中,一個類必定會與其它的類發生依賴關係。全然獨立的類是沒有意義的。

一個類同一時候依賴多個類的情況也相當普遍,既然存在這樣的情況,說明,一對多的依賴關係有它的合理性。適當的使用中介者模式能夠使原本淩亂的對象關係清晰,可是假設濫用,則可能會帶來反的效果。

一般來說,僅僅有對於那種同事類之間是網狀結構的關係,才會考慮使用中介者模式。能夠將網狀結構變為星狀結構,使同事類之間的關係變的清晰一些。
       中介者模式是一種比較經常使用的模式,也是一種比較easy被濫用的模式。對於大多數的情況,同事類之間的關係不會複雜到混亂不堪的網狀結構。因此,大多數情況下,將對象間的依賴關係封裝的同事類內部就能夠的。沒有必要非引入中介者模式。濫用中介者模式,僅僅會讓事情變的更複雜。

命令模式 意圖:將一個請求封裝為一個對象,從而可用不同的請求對客戶進行參數化。對請求排隊或記錄日誌。以及支援可撤銷的操作
動機:將”發出請求的對象”和”接收與執行這些請求的對象”分隔開來。
常見應用:
1、工作隊列,線程池。排程
2、日誌請求(系統復原)
要點:
1、命令模式將發出請求的對象和執行請求的對象解耦
2、在被解耦的兩者之間是通過命令對象進行溝通的。命令對象封裝了接收者和一個或一組動作
3、調用者通過調用命令對象的execute()發出請求。這會使得接收者的動作被調用
4、調用者能夠接受命令當作參數,甚至在執行時動態進行
5、命令能夠支援撤銷。做法是實現一個undo()方法來回到execute()被執行前的狀態
6、宏命令是命令的一種簡單的延伸,同意調用多個命令。宏方法也能夠支援撤銷
7、實際操作時。非經常見使用"聰明"命令對象,也就是直接實現了請求,而不是將工作託付給接受者(弊端?)
8、命令也能夠用來實現日誌和事物系統
責任鏈模式 使多個對象都有機會處理請求,從而避免了請求的寄件者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有對象處理它為止。

一個純的責任鏈模式要求一個詳細的處理者對象僅僅能在兩個行為中選擇一個:一是承擔責任,而是把責任推給下家。不同意出現某一個詳細處理者對象在承擔了一部分責任後又 把責任向下傳的情況。


  在一個純的責任鏈模式裡面,一個請求必須被某一個處理者對象所接收。在一個不純的責任鏈模式裡面,一個請求能夠終於不被不論什麼接收端對象所接收。
  純的責任鏈模式的實際範例非常難找到,一般看到的範例均是不純的責任鏈模式的實現。

有些人覺得不純的責任鏈根本不是責任鏈模式。這或許是有道理的。可是在實際的系統裡,純的責任鏈非常難找到。假設堅持責任鏈不純便不是責任鏈模式,那麼責任鏈模式便不會有太大意義了。

裝飾模式 又名封裝(Wrapper)模式,裝飾模式以對client透明的方式擴充項物件的功能。是繼承關係的一個替代方案。 裝飾模式與類繼承的差別:
1)    裝飾模式是一種動態行為。對已經存在類進行任意組合。而類的繼承是一種靜態行為,一個類定義成什麼樣的,該類的對象便具有什麼樣的功能,無法動態改變。


2)    裝飾模式擴充的是對象的功能,不須要添加類的數量,而類繼承擴充是類的功能,在繼承的關係中,假設我們想添加一個對象的功能,我們僅僅能通過繼承關係,在子類中添加兩個方法。
3)    裝飾與繼承比較圖:
4)    裝飾模式是在不改變原類檔案和使用繼承的情況下,動態擴充一個對象的功能,它是通過建立一個封裝對象,也就是裝飾來包裹真是的對象。


5.    裝飾模式把對client的調用委派給被裝飾的類。裝飾模式的關鍵在於這樣的擴充全然透明的。

策略模式 定義一組演算法。將每個演算法都封裝起來,並且使他們之間能夠互換。


策略模式的長處在於你能夠動態改變對象的行為。

    策略模式屬於對象行為型模式。主要針對一組演算法,將每個演算法封裝到具有共同介面的獨立的類中,從而使得它們能夠相互替換。策略模式使得演算法能夠在不影響 到client的情況下發生變化。通常。策略模式適用於當一個應用程式須要實現一種特定的服務或者功能。並且該程式有多種實現方式時使用。
適配器模式 基於現有類所提供的服務,向客戶提供介面,以滿足客戶的期望。



適配器模式的用意是要改變源的介面,以便於目標介面相容。預設適配的用意稍有不同。它是為了方便建立一個不平凡的適配器類而提供的一種平凡實現。

適配器模式的長處
  更好的複用性
  系統須要使用現有的類,而此類的介面不符合系統的須要。那麼通過適配器模式就能夠讓這些功能得到更好的複用。
  更好的擴充性
  在實現適配器功能的時候。能夠調用自己開發的功能,從而自然地擴充系統的功能。


適配器模式的缺點
  過多的使用適配器,會讓系統非常零亂,不易總體進行把握。比方,明明看到調用的是A介面。事實上內部被適配成了B介面的實現,一個系統假設太多出現這樣的情況。無異於一場災難。

因此假設不是非常有必要,能夠不使用適配器,而是直接對系統進行重構。

迭代器模式 提供一種方法訪問一個容器物件中各個元素,而又不暴露該對象的內部細節。 在jdk中,與迭代器相關的介面有兩個:Iterator 與 Iterable 
Iterator:迭代器。Iterator及其子類通常是迭代器本身的結構與方法; 
Iterable:可迭代的,那些想用到迭代器功能的其它類,如AbstractList HashMap等。須要實現該介面。

 

組合模式 將對象組合成樹形結構以表示‘部分-總體’的階層。組合模式使得使用者對單個對象和組合對象的使用具有一致性。

對象通過實現(繼承)統一的介面(抽象類別),調用者對單一對象和組合對象的操作具有一致性。
通過實現組合模式,調用者對組合對象的操作與對單一對象的操作具有一致性。

調用者不用關心這是組合對象還是檔案,也不用關心組合對象內部的詳細結構,就能夠調用相關方法,實現功能。

觀察者模式 定義對象間一種一對多的依賴關係,使得當每個對象改變狀態,則全部依賴於它的對象都會得到通知並自己主動更新。

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同一時候監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知全部觀察者對象,使它們能夠自己主動更新自己。

在JAVA語言的java.util庫裡面,提供了一個Observable類以及一個Observer介面,構成JAVA語言對觀察者模式的支援。

門面模式 外部與一個子系統的通訊必須通過一個統一的門面對象進行。

門面模式的長處:
  ●  鬆散耦合
  門面模式鬆散了client與子系統的耦合關係。讓子系統內部的模組能更easy擴充和維護。
  ●  簡單易用
  門面模式讓子系統更加易用,client不再須要瞭解子系統內部的實現,也不須要跟眾多子系統內部的模組進行互動,僅僅須要跟門面類互動就能夠了。
  ●  更好的劃分訪問層次
  通過合理使用Facade。能夠協助我們更好地劃分訪問的層次。有些方法是對系統外的,有些方法是系統內部使用的。把須要暴露給外部的功能集中到門面中。這樣既方便client使用,也非常好地隱藏了內部的細節。
備忘錄模式 在不破壞封裝性的前提下。捕獲一個對象的內部狀態。並在該對象之外儲存這個狀態。這樣就能夠將該對象恢複到原先儲存的狀態。 備忘錄對象是一個用來儲存另外一個對象內部狀態的快照的對象。

備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態捕捉(Capture)住,並外部化,儲存起來,從而能夠在將來合適的時候把這個對象還原到儲存起來的狀態。備忘錄模式經常與命令模式和迭代子模式一同使用。

訪問者模式 封裝某些作用於某種資料結構中各元素的操作。它能夠在不改變資料結構的前提下定義作用於這些元素的新的操作。
訪問者模式是對象的行為模式。訪問者模式的目的是封裝一些施加於某種資料結構元素之上的操作。一旦這些操作須要改動的話,接受這個操作的資料結構則能夠保持不變。
訪問者模式的長處
  好的擴充性
  能夠在不改動對象結構中的元素的情況下,為對象結構中的元素加入新的功能。
  好的複用性
  能夠通過訪問者來定義整個對象結構通用的功能。從而提高複用程度。
  分離無關行為
  能夠通過訪問者來分離無關的行為。把相關的行為封裝在一起,構成一個訪問者。這樣每個訪問者的功能都比較單一。

訪問者模式的缺點
  對象結構變化非常困難
  不適用於對象結構中的類經常變化的情況。由於對象結構發生了改變,訪問者的介面和訪問者的實現都要發生對應的改變,代價太高。


  破壞封裝
  訪問者模式通常須要對象結構開放內部資料給訪問者和ObjectStructrue。這破壞了對象的封裝性。

狀態模式 當一個對象的內在狀態改變時同意改變其行為。這個對象看起來像是改變了其類。
狀態模式同意一個對象在其內部狀態改變的時候改變其行為。

這個對象看上去就像是改變了它的類一樣。

 
解譯器模式 給定一種語言,定義他的文法的一種表示,並定義一個解譯器,該解譯器使用該表示來解釋語言中句子。

 
享元模式 複用我們記憶體中已存在的對象。減少系統建立對象執行個體的效能消耗。

Flyweight在拳擊比賽中指最輕量級。即“蠅量級”或“雨量級”,這裡選擇使用“享元模式”的意譯,是由於這樣更能反映模式的用意。享元模式是對象的結構模式。享元模式以共用的方式高效地支援大量的細粒度對象。
享元模式採用一個共用來避免大量擁有同樣內容對象的開銷。這樣的開銷最常見、最直觀的就是記憶體的損耗。享元對象能做到共用的關鍵是區分內蘊狀態(Internal State)和外蘊狀態(External State)。

橋樑模式 將抽象和實現解耦,使得兩者能夠獨立地變化。
橋樑模式的用意是“將抽象化(Abstraction)與實現化(Implementation)脫耦,使得二者能夠獨立地變化”。

橋樑模式在Java應用中的一個非常典型的範例就是JDBC磁碟機。JDBC為全部的關係型資料庫提供一個通用的介面。一個應用系統動態地選擇一個合適的磁碟機,然後通過磁碟機向資料庫引擎發出指令。這個過程就是將抽象角色的行為委派給實現角色的過程。

     

項目

寫了一個Android的項目體現23中設計模式,項目




測試代碼:

public void onClickSingleMode(View view) { // 單例SingleMode.getInstance();}public void onClickFactoryMethodModel(View view) {// Factory 方法IProduct iProduct = new FactoryMethodModel();iProduct.productMethod();iProduct = new Tree();iProduct.productMethod();}public void onClickAbstractFactoryModel(View view) {// 抽象工廠AbstractFactoryModel.test();}public void onClickTemplateMethodModel(View view) {// 模版方法模式TemplateMethodModel.test();}public void onClickBuilderMode(View view) {// 建造者模式BuilderMode.test();}public void onClickProxyMode(View view) {// 代理模式ProxyMode.test();}public void onClickCloneMode(View view) {// 原型模式CloneMode.test();}public void onClickIntermediaryModel(View view) {// 中介者模式IntermediaryModel.test1();IntermediaryModel.test2();}public void onClickCommandMode(View view) {// 命令模式CommandMode.test();}public void onChainOfResponsibilityModel(View view) {// 責任鏈模式ChainOfResponsibilityModel.test();}public void onClickDecorativeMode(View view) {// 裝飾模式DecorativeMode.test();}public void onClickStrategyMode(View view) {// 策略模式StrategyMode.test();}public void onClickIteratorModel(View view) {// 模式IteratorModel.test();}public void onClickCombinationMode(View view) {// 組合模式CombinationMode.test();}public void onClickObserverMode(View view) {// 觀察者模式ObserverMode.test();}public void onClickWindowMode(View view) {// 門面模式WindowMode.test();}public void onClickMemoMode(View view) {// 備忘錄模式MemoMode.test();}public void onClickVisitorMode(View view) {// 訪問者模式VisitorMode.test();}public void onClickStateModel(View view) {// 狀態模式StateModel.test();}public void onClickParserMode(View view) {// 解譯器模式ParserMode.test();}public void onClickFlyweightMode(View view) {// 享元模式FlyweightMode.test();}public void onClickBridgeMode(View view) {// 橋樑模式BridgeMode.test();}


總結

假設設計模式在編碼設計生涯中用得極少。主要原因是對設計模式的理解還不夠,認識不到問題的存在。


由於不能正確的分析問題、認識問題,當然也不可能非常好的解決這個問題了。


項目下載

Android 設計模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.