1. 簡單工廠模式 如何理解簡單工廠,工廠方法, 抽象工廠三種設計模式? 簡單工廠的生活場景,賣早點的小攤販,他給你提供包子,饅頭,地溝油烙的煎餅等,小販是一個工廠,它生產包子,饅頭,地溝油烙的煎餅。該場景對應的UML圖如下所示: 圖1:簡單工廠模式UML圖 簡單工廠模式的參與者: 工廠(Facto ...
1. 簡單工廠模式
如何理解簡單工廠,工廠方法, 抽象工廠三種設計模式?
簡單工廠的生活場景,賣早點的小攤販,他給你提供包子,饅頭,地溝油烙的煎餅等,小販是一個工廠,它生產包子,饅頭,地溝油烙的煎餅。該場景對應的UML圖如下所示:
圖1:簡單工廠模式UML圖
簡單工廠模式的參與者:
工廠(Factory)角色:接受客戶端的請求,通過請求負責創建相應的產品對象。
抽象產品(Abstract Product)角色: 是工廠模式所創建對象的父類或是共同擁有的介面。可是抽象類或介面。
具體產品(ConcreteProduct)對象:工廠模式所創建的對象都是這個角色的實例。
簡單工廠模式的演變:
1.)當系統中只有唯一的產品時,可以省略抽象產品,如圖1所示。這樣,工廠角色與具體產品可以合併。
簡單工廠模式的優缺點:
1.)工廠類含有必要的創建何種產品的邏輯,這樣客戶端只需要請求需要的產品,而不需要理會產品的實現細節。
2.)工廠類只有一個,它集中了所有產品創建的邏輯,它將是整個系統的瓶頸,同時造成系統難以拓展。
3.)簡單工廠模式通常使用靜態工廠方法,這使得工廠類無法由子類繼承,這使得工廠角色無法形成基於繼承的等級結構。
2. 工廠方法模式
工廠方法使用OOP的多態性,將工廠和產品都抽象出一個基類,在基類中定義統一的介面,然後在具體的工廠中創建具體的產品。工廠方法的生活場景,聯合利華要生產“夏士蓮”和“清揚”兩款洗髮水,它會建一個生產“夏士蓮”的工廠和一個生產“清揚”的工廠。
圖2:工廠方法的UML圖
工廠方法模式中的參與者:
抽象工廠角色:與應用程式無關,任何在模式中創建對象的工廠必須實現這個介面。
具體工廠角色:實現了抽象工廠介面的具體類,含有與引用密切相關的邏輯,並且受到應用程式的調用以創建產品對象。
抽象產品角色:工廠方法所創建產品對象的超類型,也就是產品對象的共同父類或共同擁有的介面。
具體產品角色:這個角色實現了抽象產品角色所聲名的介面。工廠方法所創建的每個具體產品對象都是某個具體產品角色的實例。
工廠方法的優缺點:
1.)降低了工廠類的內聚,滿足了類之間的層次關係,又很好的符合了面向對象設計中的單一職責原則,這樣有利於程式的拓展,如圖三所示:
圖3:工廠方法的拓展UML圖
總結:把“共性”提取出來,根據各自的“個性”建立各自的繼承共性的實現
3. 抽象工廠設計模式
所謂抽象工廠是指一個工廠等級結構可以創建出分屬於不同產品等級結構的一個產品族中的所有對象,以創建Unix控制項和Windows控制項為例說明,我們需要一個抽象工廠下麵有兩個子工廠,一個叫做UnixFactory,用於生產Unix族控制項,一個叫做WinFactory,用於生產Win族控制項。抽象工廠與工廠方法的區別是,工廠方法中的具體工廠一般只生產一個或幾個控制項對象,而抽象工廠中的具體工廠生產的是一族控制項對象。如圖4所示。
圖4:抽象工廠設計模式UML圖
抽象工廠中的參與者:
抽象工廠(Abstract Factory)角色:擔任這個角色的是工廠方法模式的核心,它是與應用系統商業邏輯無關的。
具體工廠(Concrete Factory)角色:這個角色直接在客戶端的調用下創建產品的實例。這個角色含有選擇合適的產品對象的邏輯,而這個邏輯是與應用系統的商業邏輯緊密相關的。
抽象產品(Abstract Product)角色:擔任這個角色的類是工廠方法模式所創建的對象的父類,或它們共同擁有的介面。
具體產品(Concrete Product)角色:抽象工廠模式所創建的任何產品對象都是某一個具體產品類的實例。這是客戶端最終需要的東西,其內部一定充滿了應用系統的商業邏輯。
抽象工廠的使用場景:
- 一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節,這對於所有形態的工廠模式都是重要的。
- 這個系統有多於一個的產品族,而系統只消費其中某一產品族。
- 同屬於同一個產品族的產品是在一起使用的,這一約束必須在系統的設計中體現出來。
- 系統提供一個產品類的庫,所有的產品以同樣的介面出現,從而使客戶端不依賴於實現。
抽象工廠模式與工廠方法模式的區別
工廠方法模式:每個抽象產品派生多個具體產品類,每個抽象工廠類派生多個具體工廠類,每個具體工廠類負責一個具體產品的實例創建;
抽象工廠模式:每個抽象產品派生多個具體產品類,每個抽象工廠派生多個具體工廠類,每個具體工廠負責多個(一系列)具體產品的實例創建。
//在UIKit框架下,我們用工廠方法和抽象工廠兩種設計模式分別實現了兩份Demo, 不理解兩種設計模式該如何實現的朋友可以到這裡下載: 刷不出來,以後補上!
1. 主要區別
抽象工廠 |
工廠方法 |
通過對像組合創建產品 | 通過類繼承來創建產品 |
生成一系列產品(eg:生成某類view,button,或者其他) |
生成某一種產品(eg:生成某類view) |
必須修改父類介面,才能生成新的產品 | 子類化創建者並重載工廠方法 以創建新產品 |
2. 具體的分析(以下代碼引用書上面的例子)
2.1 工廠方法
顯然,下麵的例子中PaperCanvasView和ClothCanvasView繼承自CanvasView,通過重載CanvasView的工廠方法而生成了新的一種產品。
- @interface CanvasViewGenerator : NSObject
- @implementation PaperCanvasViewGenerator
- - (CanvasView *) canvasViewWithFrame:(CGRect) aFrame {
- return [[[PaperCanvasView alloc] initWithFrame:aFrame] autorelease];
- }
- @implementation ClothCanvasViewGenerator
- - (CanvasView *) canvasViewWithFrame:(CGRect) aFrame {
- return [[[ClothCanvasView alloc] initWithFrame:aFrame] autorelease];
- }
工廠方法的應用場景:
1. 編譯時無法準備預期要生成的創建的對象的類
2. 類需要由子類決定運行時生成什麼。
2.2 抽象工廠
一樣的先上代碼:
- @interface BrandingFactory : NSObject
- + (BrandingFactory *) factory;
- - (UIView *) brandedView;
- - (UIButton *) brandedMainButton;
- - (UIToolbar *) brandedToolbar;
- @implementation BrandingFactory
- + (BrandingFactory *) factory {
- #if defined (USE_ACME)
- return [[[AcmeBrandingFactory alloc] init] autorelease];
- #elif defined (USE_SIERRA)
- return [[[SierraBrandingFactory alloc] init] autorelease];
- #else
- return nil;
- #endif
- }
- - (UIView *) brandedView {
- return nil;
- }
- - (UIButton *) brandedMainButton {
- return nil;
- }
- - (UIToolbar *) brandedToolbar{
- return nil;
- }
顯然這裡有兩個工廠,生成了一系列的產品如 UIView, UIButton, UIToolbar。而這兩個工廠又是由BrandingFactory產生的。子類需要重寫這三個方法才能生成新的產品。
抽象工廠的應用場景:
抽象工廠提供一個固定的介面,用於創建一系列由關聯或者相依存的對象,而不必指定其具體類或其創建細節。
(引 用書中的例子:雖然每家店的比薩餅不一樣,同一家比薩餅也有多種口味,但是製作的基本步驟確實一樣的。對於我們,將比薩餅看成一種食物,廚師就像是生成比 薩餅的工廠。但實際的產品的細節會有所不同。所以,廚師們都知道製作比薩餅的“通用的”或“抽象”的基本知識,但他們有自己的“實現”或“具體”,因此產 生的比薩餅不一樣)