1. 程式人生 > >二十四種設計模式、七大原則

二十四種設計模式、七大原則

轉自:http://www.taidous.com/thread-41942-1-3.html

程式:

1.可維護性 2.可複用性   3.可擴充套件性  4.靈活性好 
通過封裝、繼承、多型把程式的耦合度降低

簡單工廠模式:
用一個獨立的類來做這個創造例項的過程
聚合表示一種弱的"擁有關係",體現的是A物件可以包含B物件,但B物件不是A物件的一部分。
合成表示一種強的"擁有關係", 體現了嚴格的部分和整體的關係,部分和整體的生命週期一樣。
優點:工廠類中包含了必要的邏輯判斷,根據客戶端的選擇條件動態例項化相關的類。,對於客戶端來說,去除了與具體產品的依賴。

策略模式:
它定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的使用者。


裝飾模式:
動態地給物件新增一些額外的職責(為功能動態新增更多功能的一種方式),就增加功能來說,裝飾模式比生成子類更加的靈活。
好處:有效的把類的核心職責和裝飾功能區分開了。
裝飾模式將每個要裝飾的功能都放在單獨的類中,並讓這個類包裝它所要裝飾的物件,一次,當需要執行特殊行為時,客戶程式碼就可以在執行時根據需要有選擇地、按順序地使用裝飾功能包裝物件了。
有效的把類的核心職責和裝飾功能區分開了,而且可以去除相關類中重複的裝飾邏輯。

代理模式:
(雙方不需要知道對方的存在,通過中間人進行程式碼的呼叫)
為其他物件提供一種代理以控制對這個物件的訪問
遠端代理:也就是為一個物件在不同的地址空間提供區域性代表,這樣可以隱藏一個物件存在於不同地址空間的事實。

虛擬代理:是根據需要建立開銷很大的物件。通過它來存放例項化需要很長時間的真實物件[DP]。
安全代理:用來控制真實物件訪問的許可權[DP]。
智慧指引:是指當呼叫真實的物件時,代理處理另外一些事[DP]。


工廠方法模式:
定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類。


原型模式:
用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件
(一般在初始化的資訊不發生變化的情況下, 克隆是最好的方法。這即隱藏了物件的建立細節,又對效能是大大的提高)
淺複製:被複制物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用都仍然指向原來的物件。
深複製:把引用物件的變數都指向複製過的新物件,而不是原有的被引用的物件。

簡單來說:淺複製複製值型別,引用型別賦值的是引用的地址   深複製引用型別複製的是引用型別的物件,就是在需要改變的值的基類中宣告一個克隆方法並在具體類中呼叫


模版方法模式:
定義了一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
當我們要完成在某一細節層次一致的一個過程或一個系列步驟,但其個別步驟在更詳細的層次上的實現可能不同時,我們同城考慮使用模版方法。
通過把不變行為搬移到超類,去除子類中的重複程式碼來提現它的優勢。模版方法模式提供了一很好的程式碼複用平臺。


外觀模式:
為子系統中的一組介面提供一個一致的介面,此模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
簡單來說:就是將你一次需要呼叫的方法整理在一個接口裡面,呼叫介面,直接就呼叫了方法。


建造者模式(生成器模式):
使用者只需制定需要建造的型別就可以得到它們,而具體建造過程和細節就不需知道了。
將一個複雜物件的構造與它的表示分離,使得同樣的構建過程可以建立不同的表示。      
簡單來說:我們需要建造一樣東西,客戶端不需要知道建造過程,只需要知道要造什麼就可以了。


觀察者模式:
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽一個主題物件,這個主題物件在狀態發生變化時,會通知所有觀察者物件,使它們能夠自己更新自己。



抽象工廠模式:
提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。
好處:易於交換產品系列。具體的建立例項過程與客戶端分離。客戶端是通過它們的抽象介面操縱例項,產品的具體類名也被具體工廠的實現分離,不會出現在客戶程式碼中。


狀態模式:
當一個物件的內在狀態改變時允許改變其作為,這個物件看起來是像是改變了其類。
          將特定的狀態相關的行為都放入一個物件中,由於所有與狀態相關的程式碼都存在於某個ConcreteState中,所有通過定義新的子類可以很容易地增加新的狀態和轉換。
          簡單來說“物件的行為取決於它的狀態,並且需要在執行時改變它的狀態。那麼就應該用狀態模式。
          當你有大量的判斷語句,那麼將每一個判斷寫成一個方法。當達到某一個要求的時候,提供另外一個且只有一個方法,減少了相互之間的耦合性。



介面卡模式:
當系統的資料和行為都正確,但結構不符時,我們應該考慮用介面卡,目的就是使控制範圍之外的一個原有物件和某個介面匹配。介面卡模式主要應用於希望複用一些現存的類,但是介面又與複用環境要求不一致的情況。
            簡單來說:當兩個類需要互相呼叫,但是介面不符合的時候,就用介面卡模式,講介面適配成相同的,進行匹配。(當然,只有當無法改變原有設計和程式碼的情況下,才考慮適配模式)



備忘錄模式:
在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣以後就可將該物件恢復到原先儲存的狀態。這樣以後就可將該物件恢復到原先儲存的狀態。
    用於功能比較複雜的,但需要維護和記錄屬性歷史的類。
    缺點:會非常消耗記憶體



組合模式:
將物件組合成樹形結構以表示"部分-整體"的層次結構。組合模式使得使用者對單個物件和組合物件的使用具有一致性。
             當你發現需求中是體現部分與整體層次的結構時,以及你希望用於可以忽略組合物件與單個物件的不同,統一地使用組合結構中的所有物件時,就應該考慮組合模式。
             組合模式的體現方式有點像樹狀結構,不斷的細分下去。



迭代器模式:
提供一種方法順序訪問一個聚合物件中各個元素,而又不暴露該物件的內部表示。  
            類似於foreach迴圈
            這樣做的目的就是不讓外部訪問到內部的結構,但是可以訪問到內部的資料。


單例模式:
保證一個類僅有一個例項,並提供一個訪問它的全域性的訪問點。
          通常我們可以讓一個全域性變數使得一個物件的被訪問,但它不能放置你例項化對個物件。所以我們需要然各類自身負責儲存它的唯一例項。這個類可以爆照沒有其他例項可以被建立,並且它可以提供一個額訪問該例項的方法。
           簡單來說:就是對唯一例項的受控訪問。

          多執行緒的單例模式:在多個執行緒中,我們需要同時訪問某一個類的時候,這樣就會同時建立多個例項,所以 我們需要加一把鎖來處理(lock),如果有一個執行緒已經處在程式碼的臨界區內的時候,另外一個執行緒就需要等待,直到臨界區內的執行緒被釋放。



橋接模式:
將抽象部分與它的實現部分分離,使他們都可以獨立地變化。
          簡單來說:我們需要多角度分類的時候,可以用橋接模式,讓它們各自變化。這部分變化不會影響到其他實現。從而達到應對變化的目的,減少他們之間的耦合性。

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


職責鏈模式:
當多個物件都有機會處理這個事件的時候,就將這個物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止。


中介者模式:
用一箇中介者物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而降低耦合性。而且可以獨立地改變它們之間的互動。(缺點是:不容易維護)


享元模式:
運用共享技術有效地支援大量細粒度的物件。(當一個程式使用大量的物件的時候,就應該考慮享元模式)
          簡單來說:就是在程式的開發過程中,有許多例項大部分內容都是相同的,那麼我們就需要通過享元模式大幅度的減少單個例項的數目,從而降低伺服器的佔用資源。


直譯器模式:
給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。
            簡單來說:就是語言翻譯器的功能,當輸入一段文字後,通過返回得到一段固定不變的文字。


訪問器模式(GoF中最複雜的模式):
表示一個作用與某物件結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用與這個元素的新操作。
           訪問器模式適用於資料結構相對穩定的系統,因為它的作用是把資料結構和作用於結構上的操作之間的耦合性解脫開,使得操作集合可以相對自由地演化。(假設如果你需要增加一個新的操作的時候,就要增加一個新的訪問者,那麼訪問器模式就是講有關的行為集中到一個訪問者物件中,)




單一職責原則
  就一個類而言,應該僅有一個引起它變化的原因(如果你能夠想到多於一個的動機去改變一個類,那麼這個類就具有多一個的職責,就應該考慮類的職責分離)

開放-封閉原則
  對擴充套件是開放的。對更改是關閉的。

依賴倒轉原則
抽象不應該依賴細節,細節應該依賴於抽象
高層模組不應該依賴低層模組。兩個都應該依賴抽象

里氏代換原則
  子型別必須能夠替換它們的父型別
  只有當子類可以替換掉父類,軟在·件單位的功能不受到影響時,父類才能真正被複用,而子類也能夠在父類的基礎上增加新的行為。
  真是因為子類的可替換性才使得使用父類型別的模組在無需修改的情況下就可以擴充套件。
  如果編寫時考慮的都是如何針對抽象程式設計而不是針對細節程式設計,即程式中所有的依賴關係都是終止於抽象類或者介面,那就是面向物件的射擊,反之那就是過程化的設計。

迪米特原則
  如果兩個類不必彼此直接通訊,那麼這兩個類就不應當發生直接的相互作用,如果其中一個類需要呼叫另一個類的某一個方法的話,可以通過第三者轉發這個呼叫。

合成/聚合複用原則
    如果新物件的某些功能在別的已經建立好的物件裡面已經實現,那麼儘量使用別的物件提供的功能,使之成為新物件的一部分,而不要自己再重新建立。新物件通過向這些物件的委派達到複用已有功能的。 
簡而言之,要儘量使用合成/聚合,儘量不要使用繼承。 

介面隔離原則
不需要將所有的東西都放在一個接口裡面,應該是定義多個功能專一的介面。過於臃腫的介面只會強迫客戶依賴於不需要的方法。