關於Java設計模式的一些概況

  設計模式(Design pattern)在軟件行業一直都扮演着很重要的角色。最近感受本身對設計模式的知識有些遺忘了,雖然之前也看了不少,可是坦白說,其實並無怎麼理解。基本仍是爲了應付面試。而後,在工做當中,也不多用到那麼多的設計模式,大部分工做都是涉及單例模式,工廠模式或者裝飾模式。慢慢地,就以爲設計模式好像離本身愈來愈遠了,變成了一種似懂非懂的東西。因而乎就趕忙腦補一下。腦補的時候,感受知識確實是一種溫故而知新的東西。java

  其實,設計模式更可能是表明着一種思想,就像面向對象同樣。你在開發的過程當中,也學已經用了不少種設計模式,只是你不知道原來這就是設計模式中某一種…也由於這樣,若是你把設計模式看成一種思想思惟而不是一種工具去看待的話,那麼理解起來也會舒服和容易不少。因爲設計模式基本面向的是OOP的語言,因此OOP的思想應該是你閱讀的基礎。android

  這裏想順便插播幾句關於教育的問題。咱們一直以來都批判咱們國家的教育太過死板,總是填鴨式的教學。我我的認爲,這些真的不能算做什麼很劣質,而後外國那套很優良。咱們如今回想起來,會發現,這種咱們稱之爲填鴨式教學,其實也有它好的一面,那就是不管怎麼樣,你老是有必定理論知識的基礎。至於日後的我的發展、學習以及工做的種種影響,並不能怪罪於這種教學方式,而是咱們賦予了教育太多的使命和任務才讓本來單純傳播知識的這項任務變得如此沉重不堪……之因此,插播這個,也是但願同窗們不要去抱怨過去的鴨子,過去的鴨子再難吃也過去了,好好去捕捉其餘鳥獸吧~面試

  這篇關於設計模式主要仍是偏向概況,而且主要是關於基本的那23種模式,不會去討論如MVC、MVP或其餘MV*等衍生的設計模式。若是你對好多基本的概念不瞭解仍是先去看看一些詳細的書籍,這樣會比較好一些。好了,全部的廢話和水分都說加完了,下面開始進入乾貨模式。算法

  基礎設計模式分爲三種類型,共23種。設計模式

  建立型模式:工廠方法模式、抽象工廠模式、建立者模式、原型模式、單例模式。數組

  結構型模式:外觀模式、適配器模式、代理模式、裝飾模式、橋接模式、組合模式、享元模式。數據結構

  行爲型模式:模版方法模式、觀察者模式、狀態模式、策略模式、職責鏈模式、命令模式、訪問者模式、調停者模式、備忘錄模式、迭代器模式、解釋器模式。併發

 

  1、建立型模式  —— 該類模式研究的是若是更好地建立一個對象的問題框架

  1,工廠方法模式(Factory Pattern) —— 設計一個專門的工廠類Factory,用來專職建立一些比較複雜的對象(就是它的初始化比較複雜,不是單純new Constructor()那麼簡單)如:Bitmap bitmap = BitmapFactory.createBitmap(a,b,c);工具

 

  2,抽象工廠模式(Abstract Factory Pattern) —— 該模式是基於 工廠方法模式 。設計一個抽象的工廠接口,而後再實現它產生具體的工廠類來建立那些比較複雜的對象。當咱們須要工廠方法類解決複雜對象的建立問題並發現複雜對象屬於一系列相關聯的對象時,也即出現了對象建立的管理問題時,就能夠考慮抽象工廠方法類了。

 

  三、建立者模式(Builder Pattern)—— 當咱們須要建立一個複雜的對象,而且這個複雜的對象在使用以前的組裝也比較複雜的時候,形如Android的AlertDialog。那麼就能夠考慮使用建立者模式了。

 

  四、原型模式(Prototype Pattern)—— 當咱們須要動態建立或加載具備必定層次的對象,這些對象對外都是相對穩定的時候,原型模式就比較適合了。由於原型模式實現的基礎就是java的clone,也就是複製一個對象,而後直接操做已複製的對象。

 

  五、單例模式(Singleton Pattern)—— 該模式應該是用得比較多的模式。由於咱們常常碰到一些場景就是,只能容許有一個實例的狀況。最多的就是打印日誌了。可是咱們常常會發現一些其實原本是一種Util類型的類,卻寫成了單例,這是徹底沒有必要的。

 

  2、結構型模式 —— 建立型模式解決了關於對象建立的問題。可是對象建立後使用的過程當中,就會碰到不少對象組成以及對象與對象之間的關係管理問題。而這類問題就是結構型模式所要去解決的。

  一、外觀模式(Facade Pattern)—— 爲子系統中的一組接口提供一個一致的界面,定義一個高層接口。該模式實現了系統之間的鬆耦合關係,也使得這一子系統對外的接口更加簡潔和容易使用。

 

  二、適配器模式(Adapter Pattern)—— 一個接口所產生的結果老是固定的,可是對外則老是有各類各樣的結果需求。如何讓一個返回單一結果類型的接口,可以知足各類調用需求(固然這個需求也是創建在該接口的原始返回數據上的),這就是適配器模式所要處理的場景,該模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。

 

  三、代理模式(Proxy Pattern)—— 該模式是爲了強化一些核心類的功能。在調用目標對象的方法以前以後均可以執行特定的操做。因此,要實現代理模式,通常至少有一個abstract或interface,一個RealObject和一個ProxyRealObject,同時ProxyRealObject附帶着RealObject的應用,當外部調用接口方法時,代理類會在調用真正核心類以前以後作一項操做。

 

  四、裝飾模式(Decorator Pattern)—— 在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。經過建立一個包裝對象來包裹真實的對象,添加一些額外的職責。乍一看,其實挺像代理模式的。由於代理模式也能夠實現這樣的功能。可是你們要注意代理模式是要實現接口的。而裝飾模式更多的是爲了處理那些不適合經過生成子類來實現的,好比有大量獨立的擴展,若是爲支持每一種組合將產生大量的子類,那將會使得子類數目呈爆炸性增加。固然還有一種狀況也多是由於類的定義被隱藏,或者它是個final類不能用於生成子類。

 

  五、橋模式(Bridge)—— 有些類型因爲自身的邏輯,它可能具備多個維度的變化,如何應對這種「多維度的變化」就是橋模式所要解決的問題。好比類型A有A1,A2,A3,類型B也有B1,B2,B3,而實際使用的類型則是A*B*,也就是說若是按傳統繼承的方法則會有3*3=9種獨立的類型。任何一個維度再加1或者再增長一個維度的變化,那麼最終類型的數量就會成倍地增長並且若是後期稍有改動,維護將很是繁瑣,顯然就不太合理。咱們試試用橋模式去分析這個問題,咱們就會發現最終類型有兩個維度的變化,A*和B*的變化是獨立的也是肯定的,無法改變,可是對外提供的是A*B*倒是變化多端的。咱們應該給A和B創建一座橋,使得A和B獨立變化,自由組合。這也就是橋模式形象的解釋。

  橋接模式將繼承關係轉換爲關聯關係,從而下降了類與類之間的耦合,減小了代碼編寫量。可是在它的定義描述的是:「將抽象部分與實現部分分離,使它們均可以獨立的變化。」這裏要注意如下抽象部分並非指的是java裏面的單純的interface而是形如A與B同樣的抽象化的類型,這裏包括接口A和B,同時也包括A* 和B*;實現部分指的是最終給外部使用的部分,即A*B*組合。

 

  六、組合模式(Composite Pattern)—— 又稱部分-總體模式,組合模式使得用戶對單個對象和組合對象的使用具備一致性的操做。經典形象例子就是樹形結構的文件系統。在讓外部系統使用的時候,可讓他們統一對待目錄與文件,進行刪除增長。

 

  七、享元模式(Flyweight Pattern)—— 該模式通俗的講就是複用咱們內存中已存在的對象,下降系統建立對象實例的性能消耗。更廣義一點就是,運用共享技術有效的支持大量細粒度的對象。若是一個應用程序使用了大量相近甚至重複的對象,而這些對象形成了很大的存儲開銷的時候就能夠考慮是否可使用享元模式。

 

  3、行爲型模式 —— 對象的建立和結構都處理好了之後,新的問題又來了,就是對象的行爲要怎麼樣才更加合理,更加有效率,更加協調地與各個組件完成一系列的任務。行爲模式就是專門研究這些問題。由於行爲的多樣性,也致使了行爲型模式有不少種方案。要理解背後的思想,才能靈活運用。

  一、模板方法模式(Template Pattern)—— 就是定義一種模板邏輯來處理相似邏輯框架問題的設計模式。在面向對象開發過程當中,咱們會遇到這樣的一個問題:咱們知道一個算法所需的關鍵步驟,並肯定了這些步驟的執行順序。可是某些步驟的具體實現是未知的,或者說某些步驟的實現與具體的環境相關。好比定義一個操做順序的抽象類,其中有個final方法RunAll會依次調用run1,run2,run3,而後子類就能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。該模式的核心:封裝不變部分,擴展可變部分;行爲由父類控制,子類實現;提供公共部分代碼,便於維護。

 

  二、觀察者模式(Observer Pattern)—— 目標對象管理全部相依於它的觀察者對象,而且在它自身狀態改變時主動發出通知。該模式定義了對象間的一種一對多的依賴關係,以便一個對象的狀態發生變化時,全部依賴於它的對象都獲得通知並自動刷新。

 

  三、狀態模式(State Pattern)—— 該模式用於解決系統中複雜對象的狀態轉換以及不一樣狀態下行爲的封裝問題。當系統中某個對象存在多個狀態,這些狀態之間能夠進行轉換,並且對象在不一樣狀態下行爲不相同時,那就能夠考慮使用狀態模式了。狀態模式將一個對象的狀態從該對象中分離出來,封裝到專門的狀態類中,使得對象狀態能夠靈活變化,對於客戶端而言,無須關心對象狀態的轉換以及對象所處的當前狀態,不管對於何種狀態的對象,客戶端均可以一致處理。

 

  四、策略模式(Strategy Pattern)—— 該模式的使用場景是在項目中有多個可供選擇的算法策略,客戶端在其運行時根據不一樣需求決定使用某一具體算法策略。在實現過程爲,首先定義不一樣的算法策略,而後客戶端把算法策略做爲它的一個參數。好比java中Collections.sort()方法了,它使用Comparator對象做爲參數。根據Comparator接口不一樣實現,對象會被不一樣的方法排序。

 

  五、職責鏈模式(Chain of Responsibility Pattern)—— 在該模式裏,不少對象由每個對象對其下家的引用而鏈接起來造成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪個對象最終處理這個請求,這使得系統能夠在不影響客戶端的狀況下動態地從新組織和分配責任。就如同android中TouchEvent事件的處理同樣,它會被一層一層傳下去,若是被處理的就不往下傳了。

 

  六、命令模式(Command Pattern)—— 該模式將一個請求封裝成一個對象(參數+行爲),使客戶的不一樣請求實現了參數化。大致結構是Command接口,Command*實現類,接收者Receiver(通常是個隊列)。該模式是對行爲進行封裝的典型模式,解耦了發送者和接受者之間聯繫。 發送者調用一個操做,接受者接受請求執行相應的動做,由於使用Command模式解耦,發送者無需知道接受者任何接口。

 

  七、訪問者模式(Visitor Pattern)—— 封裝一些做用於某種數據結構中的各元素的操做,它能夠在不改變這個數據結構的前提下定義做用於這些元素的新的操做。訪問者模式的優勢是增長操做很容易,由於增長操做意味着增長新的訪問者。訪問者模式將有關行爲集中到一個訪問者對象中,其改變不影響系統數據結構。其缺點就是增長新的數據結構很困難。若是數據結構不是很穩定,那訪問者模式將不適用。

 

  八、調停者模式(Mediator Pattern)—— 該模式包裝了一系列對象相互做用的方式,使得這些對象沒必要相互明顯引用。從而使它們能夠較鬆散地耦合。當這些對象中的某些對象之間的相互做用發生改變時,不會當即影響到其餘的一些對象之間的相互做用。從而保證這些相互做用能夠彼此獨立地變化。典型的例子——電腦的CPU、顯示器、內存、聲卡、硬盤、光驅有相互聯繫的,也有不須要聯繫的。而主板就至關於調停者。若是沒有主板,那麼一個對象就要處理好幾個與之聯繫的對象。而且因爲聯繫的不一樣,每一個對象都是如此,這種系統簡稱「過分耦合系統」……而有了主板(調停者),每個對象所要處理的對象就變成了單一的調停者,調停者知道如何跟全部的配件打交道,這樣就簡單多了。

 

  九、備忘錄模式(Memento Pattern)—— 在不破壞封裝的條件下,將一個對象的狀態存儲起來並外部化,從而能夠在未來合適的時候把這個對象還原到存儲時的狀態。實現方式是建立一個備忘對象的管理類,客戶端只跟管理類耦合。如同Android系統中對Activity對象的狀態保存同樣。

 

  十、迭代器模式(Iterator Pattern)—— 主要處理集合對象,該模式的思想是提供一種方法順序訪問一個聚合對象中各個元素, 而又無須暴露該對象的內部結構。這也是java中用的最多的模式,Java的集合類均可實現迭代器模式,對集合裏面的對象進行遍歷。迭代器模式的優勢是簡化了複雜集合的遍歷方式,封裝性良好,用戶只須要獲得迭代器就能夠遍歷,而對於遍歷算法則不用去關心。可是它的缺點也很明顯,那就是不適合去處理比較簡單的(像數組或者有序列表),使用迭代器方式去遍歷簡單的裂變反而較爲繁瑣,大如同List,咱們更願意使用foreach循環去遍歷。

 

  十一、解釋器模式(Interpreter Pattern)—— 該模式就是定義語言的規則,而且創建一個解釋器來解釋該規則的語義。若是一種特定類型的問題發生的頻率足夠高,那麼就值得將該問題的各個實例表述爲一個簡單語言中的句子,天然也就須要構建一個解釋器去解釋這些句子來解決該類問題。解釋器模式在實際的系統開發中使用的很是少,由於它會引發效率、性能以及維護等問題,一般的作法是使用其餘工具甚至語言來完成這種類型的業務邏輯。

  

  結束語:知識永遠都不可能學完,可是若是你對知識進行更高層的認識而不是死記硬背,生活着任何一個點滴都能喚起你對這些知識的運用。

相關文章
相關標籤/搜索