天天看點

設計模式-總覽 單一職責原則開放-封閉原則依賴倒轉原則裡氏代換原則迪米特法則(LoD)

chapter1 簡單工廠模式

1、如何用活字印刷解釋可維護、可複用、可擴充、靈活性?

可維護:隻需要修改需要修改的文字

可複用:這些字型模型可以重複使用

可擴充:當需要增加字時,隻需要另外刻字加入即可

靈活性好:隻需要将活字子產品移動,就可以滿足排列需要

2、面向對象的好處:通過封裝、繼承、多态把程式的耦合度降低,使用設計模式使得程式更加靈活,容易修改,并且易于複用。

聚合(Aggregation):聚合表示一種弱的’擁有‘關系,展現的是A對象可以包含B對象,但B對象不是A對象的一部分。

設計模式-總覽 單一職責原則開放-封閉原則依賴倒轉原則裡氏代換原則迪米特法則(LoD)

合成/組合(Composition):是一種強的’擁有‘關系,展現了嚴格的部分和整體的關系,部分和整體的生命周期一樣。

設計模式-總覽 單一職責原則開放-封閉原則依賴倒轉原則裡氏代換原則迪米特法則(LoD)

chapter2 政策模式

面向對象的程式設計,并不是類越多越好,類的劃分是為了封裝,但分類的基礎是抽象,具有相同屬性和功能的對象的抽象集合才是類。

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

政策模式是一種定義一系列算法的方法,從概念上看,所有這些算法完成的都是相同的工作,隻是實作不同,它可以以相同的方式調用所有的算法,減少了各種算法類與使用算法類之間的耦合。

政策模式的Strategy類層次為Context定義了一系列的可供重用的算法或行為。繼承有助于析取出這些算法中的公共功能。

政策模式的優點是簡化了單元測試,因為每個算法都有自己的類,可以通過自己的接口單獨測試。

當不同的行為堆砌在一個類中時,就很難避免使用條件語句來選擇合适的行為。将這些行為封裝在一個個獨立地Strategy類中,可以在使用這些行為的類中消除條件語句。

政策模式就是用來封裝算法的,但在實踐中,我們發現可以用它來封裝幾乎任何類型的規則,隻要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用政策模式處理這種變化的可能性。

在基本的政策模式中,選擇使用具體實作的職責由用戶端對象承擔,并轉給政策模式的Context對象。

 單一職責原則

單一職責原則(SRP): 就一個類而言,應該僅有一個引起它變化的原因

如果一個類承擔的職責過多,就等于把這些職責耦合在一起,一個職責的變化可能會消弱或者抑制這個類完成其他職責的能力。這種耦合會導緻脆弱的設計,當變化發生時,設計會遭受意想不到的破壞。

軟體設計真正要做的許多内容,就是發現職責并把這些職責互相分離,如果你能夠想到多于一個動機去改變一個類,那麼這個類就具有多于一個職責。

開放-封閉原則

開放-封閉原則,也說軟體實體(類、子產品、函數等等)應該可以擴充,但不可修改。

對于擴充時開放的(open for extension),對于更改是封閉的(closed for modification)

怎樣設計才能面對需求的改變卻可以保持相對穩定,進而使得系統可以在第一個版本以後不斷推出新的版本呢?-開放-封閉

無論子產品是多麼的’封閉‘。都會存在一些無法對之封閉的變化。既然不可能完全封閉,設計人員必須對于他設計的子產品應該對那種變化封閉做出選擇。他必須先猜測出最有可能發生的變化的種類,然後構造抽象來隔離那些變化。

面對需求,對程式的改動是通過增加新代碼進行的,而不是更改現有的代碼。

開發-封閉原則是面向對象設計的核心所在。遵循這個原則可以帶來面向對象技術所聲稱的巨大好處,也就是可維護、可擴充、可複用、靈活性好。開發人員應該僅對程式中呈現出頻繁變化的那些布馮做出抽象,然而,對于應用程式中的每個部分都刻意地進行抽象同樣不是一個好主意。拒絕不成熟的抽象本身一樣重要。

依賴倒轉原則

抽象不應該依賴細節,細節應該依賴抽象,說白了,就是要針對接口程式設計,不要針對實作程式設計。

依賴倒轉:A. 高層子產品不應該依賴底層子產品。兩個都應該依賴抽象 B. 抽象不應該依賴細節。細節應該依賴抽象。

裡氏代換原則

一個軟體實體如果使用的是一個父類的話,那麼一定适用于其子類,而且它覺察不出父類對象和子類對象的差別。也就是說,在軟體裡面,把父類都替換成它的子類,程式的行為沒有變化。

裡氏代換原則(LSP): 子類型必須能夠替換掉它們的父類型。

隻有當子類可以替換掉父類,軟體機關的功能不受到影響時,父類才能真正被複用,而子類也能夠在父類的基礎上增加新的行為。

由于子類型的可替換性才使得使用父類類型的子產品在無需修改的情況下就可以擴充。

依賴倒轉其實可以說是面向對象設計的标志,用哪種語言來編寫程式不重要,如果編寫時考慮的都是如何針對抽象程式設計而不是針對細節程式設計,即程式中所有的依賴關系都是終止于抽象類或者接口。那就是針對對象的設計,反之那就是過程化的設計。

Chapter6 裝飾模式

需要把所需的功能按正确的順序串聯起來進行控制。

裝飾模式(Decorator):動态地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比子類更為靈活。

裝飾模式是為已有功能動态地添加更多功能地一種方式。當系統需要新功能地時候,是向舊類中添加新的代碼。這些新加的代碼通常裝飾了原有類的核心職責或主要行為。

在主類中加入了新的字段,新的方法和新的邏輯,進而增加了主類的複雜度。

這些新加入的東西僅僅是為了滿足一些隻在某種特定情況下才會執行的特殊行為的需要。而裝飾模式卻提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,并讓這個類包裝它所要裝飾的對象。

是以當需要執行特殊行為時,客戶代碼就可以在運作時根據需要有選擇地、按順序地使用裝飾功能包裝對象了。

裝飾模式的優點:把類中的裝飾功能從類中搬移去除,這樣可以簡化原有的類。這樣做有效地把類的核心職責和裝飾功能區分開了。而且可以去除相關類中重複的裝飾邏輯。

Chapter7 代理模式

代理模式(proxy),為其他對象提供一種代理以控制對這個對象的通路。

代理模式應用的場合:

1、遠端代理,也就是為一個對象在不同的位址空間提供局部代表。這樣可以隐藏一個對象存在于不同位址空間的事實。

2、虛拟代理,是根據需要建立開銷很大的對象。通過它來存放執行個體化需要很長時間的真實對象。

3、安全代理,用來控制真實對象通路時的權限。一般用于對象應該有不同通路權限的時候。

4、智能指針,是指當調用真實的對象時,代理處理另外一些事。

Chapter8 工廠方法模式

簡單工廠模式的最大優點在于工廠類中包含了必要的邏輯判斷,根據用戶端的選擇條件動态執行個體化相關的類,對于用戶端來說,去除了與具體産品的依賴。

工廠方法模式(Factory Method):定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。工廠方法使一個類的執行個體化延遲到其子類。

工廠方法模式實作時,用戶端需要決定執行個體化哪一個工廠來實作運算類,選擇判斷的問題還是存在的,也就是說,工廠方法把簡單工廠的内部邏輯判斷已到了用戶端 代碼來進行。你想要加功能,本來是改工廠類的,而現在是修改用戶端。

Chapter9 原型模式

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

原型模式其實就是從一個對象再建立另外一個可定制的對象,而且不需知道任何建立細節。

一般再初始化的資訊不發生變化的情況下,克隆是最好的辦法。這既隐藏了對象建立的細節,又對性能是大大的提高。

不用重新初始化對象,而是動态地獲得對象運作時的狀态。

淺複制:複制引用,被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然指向原來的對象。

深複制:複制值,深複制把引用對象的變量指向複制過的新對象,而不是原來的被引用的對象。

Chapter10 模闆方法

當我們要完成在某一細節層次一緻的一個過程或一系列步驟,但其個别步驟在更詳細的層次上的實作可能不同時,我們通常考慮用模闆方法模式來處理。

模闆方法模式,定義一個操作中的算法的骨架,而将一些步驟延遲到子類中。模闆方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

模闆方法模式的特點:模闆方法模式是通過把不變行為搬移到超類,去除子類中的重複代碼來展現它的優勢。

模闆方法模式就是提供了一個很好的代碼複用平台。

迪米特法則(LoD)

也叫最少知識原則

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

迪米特法則首先強調的前提是在類的結構設計上,每一個類都應當盡量降低成員的通路權限。

迪米特法則其基本思想,是強調了類之間的松耦合。

類之間的耦合越弱,越有利于複用,一個處在弱耦合的類被修改,不會對有關系的類造成波及。

Chapter12 外觀模式

外觀模式(Facade),為子系統中的一組接口提供一個一緻的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

Chapter13 建造者模式

将一個複雜對象的建構與它的表示分離,使得同樣的建構過程可以建立不同的表示

如果我們用了建造者模式,那麼使用者就隻需指定需要建造的類型就可以得到它們,而具體建造的過程和細節就不用知道了。

建造者模式(Builder),将一個複雜對象的建構與它的表示分離,使得同樣的建構過程可以建立不同的表示。

适用場景:建造者模式實在當建立複雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時适用的模式。

Chapter14 觀察者模式

觀察者模式又叫做釋出=訂閱(Publish/Subscribe)模式

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有觀察者對象,使他們額能夠自動更新自己。

觀察者模式的特點:當一個對象的改變需要同時改變其他對象的時候,而且不知道具體有多少對象有待改變時,應該考慮使用觀察者模式。

一個抽象模型有兩個方面,其中一方面依賴于另外一方面,這時用觀察者模式可以将這兩者封裝在獨立的對象中使他們各自獨立地改變和複用。

觀察者模式所做的工作其實就是在解除耦合。讓耦合的雙方都依賴于抽象,而不是依賴于具體,進而使得各自的變化都不會影響另一邊的變化。

事件委托:委托就是一種引用方法的類型。一旦為委托配置設定了方法,委托将與該方法具有完全相同的行為。委托方法的使用可以像其他任何方法一樣,具有參數和傳回值。委托可以看作是對函數的抽象,是函數的’類‘,委托的執行個體将代表一個具體的函數。

一個委托可以搭建多個方法,所有方法被依次喚起。它可以使得委托對象所搭載的方法不需要屬于同一個類。

委托對象所搭載的所有方法必須具有相同的原型和形式,也就是擁有相同的參數清單和傳回值類型。

Chapter15 抽象工廠模式

工廠方法模式是定義一個用于建立對象一個的接口,讓子類決定執行個體化哪一個類。

抽象工廠模式(Abstract Factory),提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。

為建立不同的産品對象,用戶端應使用不同的具體工廠。

抽象工廠模式的優點與缺點:

優點:易于交換産品系列,由于具體工廠類,在一個應用中隻需要在初始化的時候出現一次,這就使得改變一個應用的具體工廠變得非常容易,它隻需要改變具體工廠即可使用不同的産品配置。

它讓具體的建立執行個體過程與用戶端分離,用戶端是通過它們的抽象接口操縱執行個體,産品的具體類名也被具體工廠的實作分離,不會出現在客戶代碼中。

Chapter16 狀态模式

面向對象設計其實就是希望做到代碼的責任分解

狀态模式(State)當一個對象的内在狀态改變時允許改變其行為,這個對象看起來像是改變了其類。

狀态模式主要解決的是當控制一個對象狀态轉換的條件表達式過于複雜時的情況。把狀态的判斷邏輯轉移到表示不同狀态的一系列類當中,可以把複雜的判斷邏輯簡化。

将特定的狀态相關的行為都放在一個對象中,由于所有與狀态相關的代碼都存在于某個ConcreteState中,是以通過定義新的子類可以很容易地增加新地狀态和轉換,這樣做的目的就是消除龐大地分支語句。

狀态模式通過把各種狀态轉移邏輯分布到State的子類之間,來減少互相間的依賴。

當一個對象的行為取決于它的狀态,并且它必須在運作時刻根據狀态改變它的行為時,就可以考慮使用狀态模式了。

Chapter17 擴充卡模式(Adapter)

擴充卡模式(Adapter),将一個類的接口轉換成客戶希望的另外一個接口,Adapter模式使得原本由于接口不相容而不能一起工作的那些類可以一起工作。

系統的資料和行為都正确,但接口不符時,我們應該考慮用擴充卡,目的是使控制範圍之外的一個原有對象與某個接口比對。擴充卡模式主要應用于希望複用一些現存的類,但是接口又與複用環境要求不一緻的情況。

适用場景:使用一個已經存在的類,但如果它的接口,也就是它的方法和你的要求不相同時,就應該考慮用擴充卡模式,兩個類所做的事情相同或相似,但是具有不同的接口時要使用它。

客戶代碼可以統一調用同一接口就行了,這樣應該可以更簡單、更直接、更緊湊。

在雙方都不太容易修改的時候再使用擴充卡模式适配

Chapter18 備忘錄模式

備忘錄(Memento):在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可将該對象恢複到原先儲存的狀态。

如果需要儲存的不是全部資訊,而隻有部分,那麼就應該有一個獨立的備忘錄類Memento,它隻擁有需要儲存的資訊的屬性,

Chapter19 組合模式

組合模式(Composite),将對象組合樹形結構以表示’部分-整體‘的層次結構。組合模式使得使用者對單個對象群組合對象的使用具有一緻性。

适用場合:需求中是展現部分與整體層次的結構時,以及你希望使用者可以忽略組合對象與單個對象的不同,統一地使用組合結構中的所有對象時,就應該考慮組合模式了。

Chapter20 疊代器模式

疊代器模式(Iterator),提供一種方法順序通路一個聚合對象中各個元素,而又不暴露該對象的内部表示。

當你需要通路一個聚集對象,而且不管這些對象是什麼都需要周遊的時候,你就應該考慮用疊代器模式。

需要對聚集有多種方式周遊時,可以考慮用疊代器模式。

為周遊不同的聚集結構提供如開始、下一個、是否結束、目前哪一項等統一的結構。

疊代器(Iterator)模式就是分離了集合對象的周遊行為,抽象出一個疊代器類來負責,這樣既可以做到不暴露集合的内部結構,又可讓外部代碼透明地通路集合内部地資料。

Chapter21 單例模式

所有類都有構造方法,不編碼則系統預設生成空的構造方法,若有顯示定義的構造方法,預設的構造方法就會失效。

單例模式(Singleton),保證一個類僅有一個執行個體,并提供一個通路它的全局通路點。

”通常我們可以讓一個全局變量使得一個對象被通路,但它不能通路你執行個體化多個對象。一個最好的辦法就是,讓類自身負責儲存它的唯一執行個體。這個類可以保證沒有其他執行個體可以被建立,

并且它可以提供一個通路該執行個體的方法。“

Singleton類:定義一個GetInstance操作,允許客戶通路它的唯一執行個體,GetInstance是一個靜态方法,主要負責建立自己的唯一執行個體。

單例模式因為Singleton類封裝它的唯一執行個體,這樣它可以嚴格地控制客戶怎樣通路它以及何時通路它。簡單地說就是對唯一執行個體的受控通路。

多線程時的單例,lock是確定當一個線程位于代碼的臨界區時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼,則它将一直等待(即被阻止),直到該對象被釋放。

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		static Singleton  singleton;//此變量存在靜态區,C++11自帶兩段檢查鎖機制來確定static變量執行個體化一次
		return &singleton;
	}
private:
	Singleton();
};
 
int main()
{
	auto p1 = Singleton::GetInstance();
	auto p2 = Singleton::GetInstance();
	bool result=( p1 == p2);
	std::cout <<  result << std::endl;
 
	return 0;

————————————————
版權聲明:本文為CSDN部落客「Lailikes」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/songchuwang1868/article/details/87882778
           

Chapter22 橋接模式

對象的繼承關系是在編譯時就定義好了,是以無法在運作時改變從父類繼承的實作。子類的實作與它的父類有非常緊密的依賴關系,以至于父類實作中的任何變化必然會導緻子類

發生變化。當你需要複用子類時,如果繼承下來的實作不适合解決新的問題,則父類必須重寫或被其他更适合的類替換。這種依賴關系限制了靈活性并最終限制了複用性。

合成/聚合複用原則(CARP),盡量使用合成/聚合,盡量不要使用類繼承。

聚合表示一種弱的‘擁有’關系,展現的是A對象可以包含B對象,但B對象不是A對象的一部分;

合成是一種強的‘擁有’關系,展現了嚴格的部分和整體的關系,部分和整體的生命周期一樣。

合成/聚合複用原則的好處是,優先使用對象的合成/聚合将有助于你保持每個類被封裝,并被集中在單個任務上,這樣類和類繼承層次會保持較小規模,并且不太可能增長為不可控制的龐然大物。

橋接模式(Bridge),将抽象部分與它的實作部分分離,使它們都可以獨立地變化。

抽象與它的實作分離指的是抽象類和它的派生類用來實作自己的對象。

實作系統可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來讓它們獨立變化,減少它們之間的耦合。

适用場合:在發現需要多角度去分類實作對象,而隻用繼承會造成大量的類增加,不能滿足開放-封閉原則時,就應該要考慮橋接模式了。

Chapter23 指令模式

指令模式(Command),将一個請求封裝為一個對象,進而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支援可撤銷操作。

優點:指令模式把請求一個操作的對象與知道怎麼執行一個操作的對象分割開

指令模式作用:

第一:它能較容易地設計一個指令隊列;

第二:在需要的情況下,可以較容易地将指令記入日志;

第三:允許接收請求的一方決定是否要否決請求;

第四:可以容易地實作對請求地撤銷和重做;

第五:由于加進新的具體指令類不影響其他類,是以增加新的具體指令類很容易;

靈活開發原則:不要為代碼添加基于猜測的、實際不需要的功能。如果不清楚一個系統是否需要指令模式,一般就不要着急去實作它,

事實上,在需要的時候通過重構實作這個模式并不困難,隻有在真正需要如撤銷/恢複操作等功能時,把原來的代碼重構為指令模式才有意義。

Chapter24 職責鍊模式

職責鍊模式(Chain of Responsibility): 使多個對象都有機會處理請求,進而避免請求的發送者和接收者之間的耦合關系。将這個對象連成一條鍊,并沿着這條鍊傳遞該請求,直到有一個對象處理它為止。

好處:當客戶送出一個請求時,請求是沿鍊傳遞直至一個ConcreteHandler對象負責處理它。這就使得接收者和發送者都沒有明确的資訊,且鍊中的對象自己也并不知道鍊的結構。結果是職責鍊可簡化對象的互相連接配接,

它們僅需保持一個指向其後繼者的引用,而不需要保持它所有的候選接受者的引用。

可以随時地增加或修改處理一個請求的結構。增強了給對象指派職責的靈活性。

一個請求極有可能到了鍊的末端都得不到處理,或者因為沒有正确配置而得不到處理。

Chapter25 中介者模式

盡管将一個系統分割成許多對象通常可以增加其可複用性,但是對象間互相連接配接的激增又會降低其可複用性了。

大量的連接配接使得一個對象不可能在沒有其他對象的支援下工作,系統表現為一個不可分割的整體,是以,對系統的行為進行任何較大的改動就十分困難了。

中介者模式(Mediator),用一個中介對象來封裝一系列的對象互動。中介者使各對象不需要顯示地互相引用,進而使得其耦合松散,而且可以獨立地改變它們之間地互動。

優缺點:中介者模式很容易在系統中應用,也很容易在系統中誤用。當系統出現了‘多對多’互動複雜地對象群時,不要急于使用中介者模式,而要先反思你的系統在設計上是不是合理。

Mediator的出現減少了各個College的耦合,使得可以獨立地改變和複用各個Colleague類和Mediator,比如各個國家地改變不會影響到其他國家,而隻是與安理會發生變化。其次,

由于把對象如何協作進行了抽象,将中介作為一個獨立地概念并将其封裝在一個對象中,這樣 關注地對象就從對象各自本身地行為轉移到他們之間地互動上來,也就是站在一個更宏觀地角度去看待系統。

由于ConcreteMediator控制了集中化,于是就把互動複雜性變為了中介者的複雜性,這就使得中介者會變得比任何一個ConcreteColleague都複雜。

Chapter26 享元模式

享元模式(Flyweight),運用共享技術有效地支援大量細粒度的對象。

一個享元工廠,用來建立并管理Flyweight對象。它主要是用來確定合理地共享Flyweight對象,當使用者請求一個Flyweight時,FlyweightFactory對象提供一個已建立的執行個體或者建立一個(不存在的話)。

内部狀态和外部狀态:享元模式可以避免大量細粒度的類執行個體來表示資料,如果能發現這些執行個體除了幾個參數外基本上都是相同的,有時就能夠受大幅度地減少需要執行個體化地類地數量。如果能把那些參數

移到類執行個體地外面,在方法調用時将它們傳遞進來,就可以通過共享大幅度地減少單個執行個體地數目。

适用場景:如果一個應用程式使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時就應該考慮适使用;還有就是對象地大多數狀态可以外部狀态,如果删除對象地外部狀态,那麼可以用相對較少

的共享對象取代很多組對象,此時可以考慮使用享元模式。

Chapter27 解釋器模式

解釋器模式Z(interpreter),給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

解釋器需要解決的是,如果一種特定類型的問題發生的頻率足夠高,那麼可能就值得将該問題的各個執行個體表述為一個簡單語言中的句子。這樣就可以建構一個解釋器,該解釋器通過解釋這些句子來解決該問題。

Chapter28 通路者模式

通路者模式(Visitor),表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

通路者模式适用于資料結構相對穩定的系統,它把資料結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。

通路者模式的目的是要把處理從資料結構分離出來。很多系統可以按照算法和資料結構分開,如果這樣的系統有比較穩定的資料結構,又有易于變化的算法的話,使用通路者模式就是比較合适的,因為通路者模式使得算法操作

的增加變得容易。反之,如果這樣的系統的資料結構對象易于變化,經常要有新的資料對象增加進來,就不适合使用通路者模式。

優點:就是增加新的操作很容易,因為增加新的操作就意味着增加一個新的通路者。通路者模式将有關的行為集中到一個通路者對象中。

缺點:增加新的資料結構變得困難了。

繼續閱讀