設計模式之簡單工廠模式

2021-07-25 02:01:55 字數 3088 閱讀 3789

設計模式之簡單工廠模式

動機:        不暴露例項化邏輯來建立物件。通過公共的介面建立新的物件。

這是乙個簡單的實現,客戶端需要乙個product,但是client不直接使用new物件,而是通過提供需要的物件資訊來找factory得到新的product。

這個factory例項化乙個具體的product並返回**化成抽象的類),client段使用這個抽象的類而不用考慮它具體的實現。

應用舉例:        也許工廠模式是使用最多的模式之一。舉個例子,乙個操作影象的圖形應用。在我們實現繪畫的模組就是client,而那些shapes圖形就是products,所有的圖形都繼承自乙個abstract shape抽象的形狀類(或者介面)。 這個abstract shape定義了繪畫draw和move方法去讓子類實現。讓我們假設有個建立圓形的命令,client接收乙個string型別的圖形型別引數,client從factory得到concrete shape轉換成abstract shape。

這樣的好處是很顯然的:新增乙個圖形不用修改client的**,只要在factory的實現裡面增加新的型別即可。

詳細問題和解決方法:

新手使用switch/case引數化factory,生成product的方法可以被重寫,所以factory可以生成更多型別的product物件,使用乙個條件(輸入乙個方法引數或者一些全域性配置引數)頭標識哪種product物件應該被建立。**如下:

public class productfactory

...}        這種實現方法是簡單直接的(讓我們稱之為新手實現),這裡的問題就是,新增一種product我們就要修改factory類,不夠彈性,違反了開閉原則。當然我們可以繼承factory類,但是別忘了factory類通常是單例的。

註冊類-使用反射reflection:

如果你可以使用反射,就可以在不修改factory的前提下註冊新的product類。在不知道product型別的前提下我們在facoty中建立product物件,我們可使用map儲存productid和product type,在這種情況下,新增乙個新的product,需要在map中註冊該product,這個操作不需要修改factory的**:

class productfactory

public product createproduct(string productid)

);return (product)(new object );

}}        我們可以把registion code註冊**放在任何地方,但是使用static靜態**塊在product類裡面註冊是乙個方便的方法,看下面的例子:

1、在product類外面註冊:

public static void main(string args) 

2、在product類裡面註冊:

class oneproduct extends product

...}        我們必須確保在factroy使用concrete product具體的product之前完成註冊,不然就會出現null point空指標,我們在main類的static靜態**塊中使用方法。方法支援返回乙個類的例項,如果乙個編譯器沒有載入這個類,編譯器就會在被呼叫的時候載入。

class main

catch (classnotfoundexception any)

}public static void main(string args) throws phonecallnotregisteredexception

}        這種反射實現有它的壞處,乙個主要的壞處就是它的效能表現,使用反射要比不使用反射效能表現降低10%。

註冊類-不使用反射:

在之前的段落中我們看到facotory使用map儲存productid和product type,這個註冊器在factory外面實現,因為通過使用反射不用再關心所要建立物件的型別。

我們不想使用反射,但是同時factory又不需要考慮product型別。我們在product abstract class裡面新增乙個新的abstract方法,每個具體的類都要實現設個方法去創造自己。我們也不得不改變註冊器這樣我們將註冊具體的product物件。

abstract class product

class oneproduct extends product

public oneproduct createproduct()

...}class productfactory

public product createproduct(string productid)

}乙個更高階的解決方法-使用抽象工廠abstract factory(工廠方法 factory method):

這種實現代表乙個可修改的註冊器類實現,假設我們新增乙個新的product,使用過程化的switch/case我們需要修改factory類的**,而使用註冊器類,我們要做的只是把註冊器類給factory,而不用修改factory,這肯定是乙個彈性的解決方式。

過程化的實現方式是典型的違背開閉原則的壞例子,我們能看到有很多擴充套件factory的直接解決方法去避免修改factory。

工廠方法模式factory method pattern經典的實現方式有一些壞處通過註冊器,而沒有很多的好處:

好處:當product物件被建立的時候,繼承的factory method可以被修改去表現新增的操作。

壞處:    1、factory必須要用singleton實現。

2、每個factory必須要在使用前先例項化。

3、實現起來有更多的困難。

4、如果乙個新的product要被建立,乙個新的factory要被建立。

不管怎麼樣,經典的實現方式有它的好處,可以幫助我們理解抽象工廠模式abstract factory pattern。

(if (concreteproduct)genericproduct typeof )

((concreteproduct)genericproduct).dosomeconcreteoperation().

如果你決定使用factory模式,我會推薦你使用帶註冊器的實現(使用反射或者不使用反射都行),避免使用factory method,記住switch/case是最簡單,違反開閉原則,只是用來解釋factory原理的。

設計模式 工廠模式之簡單工廠模式

定義 由乙個工廠物件 工廠類 來指定建立某乙個產品類的例項。使用場景 客戶端只需傳入指定的引數即可,工廠類負責建立的物件較少 因為指定了傳入的引數 介面類 本想用iphone命名的,見諒 public inte ce phone實現介面類 public class huaweiphone imple...

設計模式 工廠模式之簡單工廠

工廠模式可以分為 簡單工廠模式 普通工廠模式 靜態工廠模式 抽象工廠模式 簡單工廠模式 就是如何去例項化物件的問題,對於很容易變化的問題,應該考慮用乙個單獨的類來做這個創造例項的過程,這個單獨的類就是工廠 例子 通過簡單工廠建立各種圖形的實現過程 簡單工廠模式建立步驟 建立乙個介面 例 圖形介面 建...

設計模式 工廠模式之簡單工廠

我們常見的設計模式,大致可以分為三大類 建立型 結構性 行為型。工廠模式,屬於建立型。工廠模式到底起的是什麼作用呢?概括來說就是解耦。當某一類物件需要頻繁建立的時候,就會和程式產生比較大的耦合,在物件初始化屬性較多時,工廠模式可以較少這種耦合,這就是他的作用。一般情況下根據場景不同,工廠模式有幾種不...