天天看點

【我的《冒号課堂》學習筆記】設計模式(1)建立模式

建立模式

每個設計模式的提出是基于問題的,OOP是以對象為中心的,可對象從何而來?最普遍的作為是通過關鍵字new和構造器(constructor)。然後從設計的角度看,這種做法卻可能存在一定的問題。

構造器第一個弊端:它的名字必須和類名一緻,缺乏足夠的表現力。

  比如,用Point類來代表平面坐标系的點,它的構造器将有兩個參數,分别為橫坐标和縱坐标。有時候,我們還希望用極坐标來構造一個點。

  盡管兩個構造器參數名不同,但是它們方法簽名沖突。

靜态工廠方法(static factory method)可解此困局。

【我的《冒号課堂》學習筆記】設計模式(1)建立模式
【我的《冒号課堂》學習筆記】設計模式(1)建立模式

這樣處理後代碼的可讀性和直覺性明顯增強,美中不足的是該類無法被繼承,因為它的構造器是私有的。但此例而言并無被繼承的必要。但毋庸置疑,這的确是一個問題,好在我們更提倡用合成來代替繼承。

構造器第二個弊端:它的每次調用都伴随着新對象的建立,但這并不總是合适的。

如果不公開構造器,而借助靜态工廠方法來提供對象,便可控制對象執行個體的個數。一方面是出于管理方面的原因,比如單例模式(singleton pattern)便是一個典型的應用;另一個方面是出于性能方面的原因,比如可利用對象池(object pool)來減少對象的建立。最簡單的例子莫過于Java中Boolean類提供的valueOf方法

valueOf不會建立新對象,因為它傳回的總是Boolean.TRUE和Boolean.FALSE中的一個。由于Boolean類是不可變的(immutable),共享對象不會産生任何問題。在文檔中有valueOf方法代替構造器的建議。

構造器第三個弊端是它無法被繼承,也就無法多态。

很多時候,客戶隻關心建立的對象是否能提供某種特定的服務,即在乎的是該對象的社會身份——某個抽象的超類型,而不是它的個體身份——具體類型。可是如果客戶直接通過new來建立對象,就必須知道對象的具體類型,進而違背了針對接口程式設計的原則。此時靜态工廠方法再顯身手,它可以傳回一個具有指定接口的對象,對象的具體類型則不用透露給客戶。這些具體類型可以是公開的,也可以是非公開的,還可以是運作期間決定的,甚至可以是動态加載的。

此外,或因設計上的缺陷,或因對象本身的複雜性,不少構造器并沒有完成全部的初始化。這不僅會給客戶帶來額外的負擔,也可能破壞對象的一緻性。更糟糕的是,這部分邏輯随時可能變化,維護起來很不友善。最好的辦法是這種變化隔離出來,單獨封裝在一個子產品中。這個子產品可以是一個方法——工廠方法,也可以是一個類——工廠類。

後面的靜态工廠 工廠 抽象工廠 建造者模式略

設計模式具體以後另外寫筆記

【我的《冒号課堂》學習筆記】設計模式(1)建立模式
【我的《冒号課堂》學習筆記】設計模式(1)建立模式

繼續閱讀