探索設計模式之三 抽象工廠模式

2021-08-30 10:19:47 字數 3562 閱讀 1499

前面介紹的「簡單工廠模式」和「工廠方法模式」,立足點都是避免顯式的建立具體物件,封裝建立物件時可能出現的變化點,這已經能比較好的解決單個物件建立的問題,但實際業務中,還經常出現需要一系列物件互相關聯使用來完成任務的情況。對於存在關聯、以來的產品來說,使用簡單工廠或者工廠方法乙個乙個的建立其中的具體產品,經常無法達到理想的效果。譬如,「西裝」和」短褲」都分別實現了「上衣」,「褲子」介面,分別套在身上一點問題都沒有,但是實際上卻不太可能穿著西裝和短褲上街。

通過簡單工廠或者工廠方法乙個乙個地單獨建立產品然後再合併使用除了有可能出現上面「西服+短褲」的笑話外,使用者在使用組合產品的時候,通常是不關心產品具體成員的建立過程的,因此也不應當把各個產品的建立過程揉合到具體邏輯之中。為了解決上面的問題,就gof經典設計模式中就出現了本章的主角——抽象工廠模式。

目的:

建立一系列互相關聯或者互相以來的組合產品。

場景:

隨著遊戲的發展,前期小打小鬧的試探進攻時期已經過去。我們要考慮的問題也已經不再是乙個機槍兵能否戰勝乙隻小狗、乙個火兵能否打贏乙隻刺蛇(見簡單工廠模式)了。遊戲中期要佔得先機,關鍵不在一兵一卒,而在戰術正確與否。

星際爭霸多年的遊戲發展中,出現過無數天馬行空的戰術和激動人心的戰例。其中,在terran在對抗terran和zerg時,有兩種主流戰術如下:

tvt:主力兵種使用坦克,維護兵種是scv,空軍選擇wraith(隱飛)

tvz:主力兵種使用槍兵,維護兵種是medic(**),空軍選擇science vessel(科學球)

分析:

只要對手的種族一確定,我們的戰術就定下來,也就是選擇的兵種就定下了。出戰的時候,都是框一圈兵a過去(-_-#),並不關心裡面某個兵是什麼時候、如何被生產出來的,關心的只是這組部隊能不能優勢互補,贏得戰爭。這符合抽象工廠的使用場景。現在,就通過抽象工廠模式,看看上述兩種戰術中的兵種組合是如何使用**演繹的。

照例,我們先看一下這次需要涉及到的工廠和產品類圖及**:

圖3.1 戰鬥部隊及工廠的uml圖

public inte***ce iattackunit 

public inte***ce iairunit

public inte***ce imedicalunit

public class marine implements iattackunit

public void attack() }

public class medic implements imedicalunit

public void cure() }

public class sciencevessel implements iairunit

public void assist() }

public class scv implements imedicalunit

public void cure() }

public class tank implements iattackunit

public void attack() }

public class wraith implements iairunit

public void assist()

}

在上述**中,「iattackunit、iairunit、imedicalunit」是抽象產品,實現這三個介面的「tank、scv、marine……」等則是具體產品,關於抽象產品、具體產品等概念在前一章已經介紹過。現在我們繼續看看如何通過工廠來為抽象產品選擇具體的實現類的。

抽象工廠和具體工廠的實現**如下:

public inte***ce iarmyfactory 

public class tvtarmyfactory implements iarmyfactory

// 空中單位是隱飛

public iairunit createairunit()

// 主攻單位是坦克

public iattackunit createattackunit()

// 醫療單位是scv

public imedicalunit createmedicalunit() }

public class tvzarmyfactory implements iarmyfactory

// 空中單位是科學球

public iairunit createairunit()

// 主攻單位是槍兵

public iattackunit createattackunit()

// 醫療單位是**

public imedicalunit createmedicalunit()

}

客戶端呼叫**如下:

public class warfield 

public static void main(string args)

}

從**上可以看出,每乙個具體工廠的目的都不是創造單個的具體產品,而是過把整個產品家族(iattackunit、iairunit、imedicalunit)的所有具體產品都創造出來,這樣各個具體產品之間的聯絡就通過乙個具體工廠來體現。當需要新增乙個產品家族,或者已有產品家族的構成成員發生變化的時候,影響也就侷限在了某乙個具體工廠之中。業務邏輯所依賴的都是抽象工廠和抽象產品,具體產品變化的影響就這樣從業務邏輯中隔離開來。

這種通過依賴抽象類(或者介面)來削弱耦合、隔離變化點的方法,在設計模式中被總結為乙個重要原則——依賴倒轉原則:業務邏輯應該依賴於抽象類,而不應該依賴於具體實現類。「依賴倒轉」中的「倒轉」,指得就是人們直觀思維之中,高層邏輯應當依賴與他下面的功能點分解,功能點分解又依賴於底層功能這種自上而下層層依賴的開發思想。這種開發思想中,任何底層的變化都有可能導致產生對上層的影響,同時,上層需求有改動的時候,又同樣需要下層改動提供支援,這樣當軟體層次累計得越來越高的時候,變化就越來越可能引起上下層間的反覆傳遞,導致嚴重的後果——牽一髮而動全身。

物件導向中耦合關係有三種:零耦合、抽象耦合、具體耦合。依賴反轉原則的本質意圖就是將具體耦合削弱為抽象耦合。從下面兩張圖上可以看出,在互相依賴的模組中加入一層「抽象層」後,上層業務邏輯、下層具體實現的變化都受抽象類的隔離,變化就相對不容易在各層之間擴散。

圖3.2 自上而下的依賴關係

圖3.3 依賴反轉

如果說開閉原則(見第二章)是設計模式追求的目標,那依賴反轉原則就是設計模式的最基本、普遍的解決問題思路。從面向具體類程式設計到面向介面程式設計的轉變,是乙個程式設計師從**實現者到設計者進化的標誌。

最後,展示一下程式的最終執行結果:

圖 3.2 兩種兵種組合

總結:

經過三章關於「工廠模式」的介紹,我們對通過工廠來建立產品,隱藏具體實現和建立細節的做法已經有了一定的了解。物件的產生,除了直接使用new和使用工廠封裝外,還有幾種其他方式。在這邊terran部隊建設如火如荼的時候,且看看那邊zerg的發展情況如何,看看其他幾種建立模式是如何在zerg中發揮作用的。

每日設計模式 工廠模式之三(抽象工廠模式)

抽象工廠又叫做工廠的工廠。從某個角度來說抽象工廠是工廠方法模式的公升級版。工廠方法模式相對簡單,只負責某一類產品的建立工作,而工廠方法模式很強大,能建立很多的產品,從這個角度來說抽象工廠模式確實是工廠方法模式的公升級。但是,從職能和應用場景上來看,不應該將抽象工廠看成是工廠方法模式的公升級版。工廠方...

設計模式筆記之三抽象工廠模式

為什麼引入抽象工廠模式?乙個介面代表一系列操作,當我們需要的物件需要多個介面,而這些介面又是不相干的,同時對於類的建立我們不需要知道具體的實現細節,只需要知道某個特徵就可以,雖然工廠方法模式可以滿足要求,但是工廠方法模式會讓類本身實現很多不相關的操作,同時增加了物件內部的複雜性,我們需要一種從更高層...

設計模式之三 工廠模式

如果要擴充套件的話,則要修改源 這樣如果以後產生的phone型別很多,那麼就要一直修改,維護成本高 如果萬一你哪個型別寫錯了怎麼辦 所以出現了工廠模式。工廠模式簡單來說就是乙個工廠對應乙個產品。比如說iphonefactory產生iphone系列的手機,xiaomifactory產生xiaomi系列...