1 前言
上篇文章我們介紹了工廠方法模式,已經充分的體會到了工廠模式的優越性, 但是如果産品再進行細化的時候我們就該用到了抽象工廠模式。這節我們将接觸到産品族等概念。閑話少說,馬上步入正題吧。
轉載請注明出處:http://blog.csdn.net/developer_zhang
2 詳述
2.1 定義
定義:為建立一組相關或互相依賴的對象提供一個接口,而且無需指定他們的具體類。
2.2 簡單工廠,工廠方法與抽象工廠對比
簡單工廠:工廠可以建立同一系列的産品,産品的接口一緻,但工廠就要根據參數進行判斷到底建立哪種産品
賣早飯的張婆婆:可以做茶葉蛋,包子,稀飯
工廠方法:可以有多種工廠,工廠有共同的接口,一個工廠隻能産生一種産品,比起簡單工廠,工廠方法就不需要判斷,耦合度低了不少
劉老闆:隻賣包子的包子鋪,隻賣稀飯的稀飯莊
抽象工廠:可以産生多個系列的産品,有2個次元的産品
KFC老闆:可樂系列産品、漢堡系列産品,每種系列産品又分大,中,小三種。
如果這樣來看應該很容易就能區分他們之間的關系了。
2.3 産品族
為了友善引進抽象工廠模式,引進一個新概念:産品族(Product Family)。所謂産品族,是指位于不同産品等級結構,功能相關聯的産品組成的家族。如圖:
圖中一共有四個産品族,分布于三個不同的産品等級結構中。隻要指明一個産品所處的産品族以及它所屬的等級結構,就可以唯一的确定這個産品。
所謂的産品族,是指位于不同産品等級結構中功能相關聯的産品組成的家族。
可能大家還是看不太懂舉個例子吧:比如AMD的主機闆、晶片組、CPU組成一個家族,Intel的主機闆、晶片組、CPU組成一個家族。而這兩個家族都來自于三個産品等級:主機闆、晶片組、CPU。一個等級結構是由相同的結構的産品組成,示意圖如下:
顯然,每一個産品族中含有産品的數目,與産品等級結構的數目是相等的。産品的等級結構與産品族将産品按照不同方向劃分,形成一個二維的坐标系。橫軸表示産品的等級結構,縱軸表示産品族,上圖共有兩個産品族,分布于三個不同的産品等級結構中。隻要指明一個産品所處的産品族以及它所屬的等級結構,就可以唯一的确定這個産品。
上面所給出的三個不同的等級結構具有平行的結構。是以,如果采用工廠方法模式,就勢必要使用三個獨立的工廠等級結構來對付這三個産品等級結構。由于這三個産品等級結構的相似性,會導緻三個平行的工廠等級結構。随着産品等級結構的數目的增加,工廠方法模式所給出的工廠等級結構的數目也會随之增加。如下圖:
那麼,是否可以使用同一個工廠等級結構來對付這些相同或者極為相似的産品等級結構呢?當然可以的,而且這就是抽象工廠模式的好處。同一個工廠等級結構負責三個不同産品等級結構中的産品對象的建立。
可以看出,一個工廠等級結構可以建立出分屬于不同産品等級結構的一個産品族中的所有對象。顯然,這時候抽象工廠模式比簡單工廠模式、工廠方法模式更有效率。對應于每一個産品族都有一個具體工廠。而每一個具體工廠負責建立屬于同一個産品族,但是分屬于不同等級結構的産品。
2.4 抽象工廠模式的優點
(1)分離接口和實作
用戶端使用抽象工廠來建立需要的對象,而用戶端根本就不知道具體的實作是誰,用戶端隻是面向産品的接口程式設計而已。也就是說,用戶端從具體的産品實作中解耦。
(2)使切換産品族變得容易
因為一個具體的工廠實作代表的是一個産品族,比如上面例子的從Intel系列到AMD系列隻需要切換一下具體工廠。
2.5 抽象工廠模式的缺點
不太容易擴充新的産品:如果需要給整個産品族添加一個新的産品,那麼就需要修改抽象工廠,這樣就會導緻修改所有的工廠實作類。
2.6 抽象工廠結構
抽象工廠模式是對象的建立模式,它是工廠方法模式的進一步推廣。
假設一個子系統需要一些産品對象,而這些産品又屬于一個以上的産品等級結構。那麼為了将消費這些産品對象的責任和建立這些産品對象的責任分割開來,可以引進抽象工廠模式。這樣的話,消費産品的一方不需要直接參與産品的建立工作,而隻需要向一個公用的工廠接口請求所需要的産品。
通過使用抽象工廠模式,可以處理具有相同(或者相似)等級結構中的多個産品族中的産品對象的建立問題。如下圖所示:
根據産品角色的結構圖,就不難給出工廠角色的結構設計圖。
可以看出,每一個工廠角色都有兩個工廠方法,分别負責建立分屬不同産品等級結構的産品對象。
抽象工廠的功能是為一系列相關對象或互相依賴的對象建立一個接口。一定要注意,這個接口内的方法不是任意堆砌的,而是一系列相關或互相依賴的方法。比如上面例子中的主機闆和CPU,都是為了組裝一台電腦的相關對象。不同的裝機方案,代表一種具體的電腦系列。
由于抽象工廠定義的一系列對象通常是相關或互相依賴的,這些産品對象就構成了一個産品族,也就是抽象工廠定義了一個産品族。
這就帶來非常大的靈活性,切換産品族的時候,隻要提供不同的抽象工廠實作就可以了,也就是說現在是以一個産品族作為一個整體被切換。
2.7 何時使用
(1)一個系統不應當依賴于産品類執行個體如何被建立、組合和表達的細節,這對于所有形态的工廠模式都是重要的。
(2)這個系統的産品有多于一個的産品族,而系統隻消費其中某一族的産品。
(3)同屬于同一個産品族的産品是在一起使用的,這一限制必須在系統的設計中展現出來。(比如:Intel主機闆必須使用Intel CPU、Intel晶片組)
(4)系統提供一個産品類的庫,所有的産品以同樣的接口出現,進而使用戶端不依賴于實作。
2.8 執行個體代碼
下面我們來看看上面這個執行個體的代碼:
CPU父類:
#import <Foundation/Foundation.h>
/*!
* CPU父類
*
* @since V1.0
*/
@interface CpuBase : NSObject
@property int pins;//針腳數
-(void)calculate;
@end
Intel的CPU子類:
#import "CpuBase.h"
/*!
* Intel的CPU子類
*
* @since V1.0
*/
@interface IntelCPU : CpuBase
@end
MainBoard父類:
#import <Foundation/Foundation.h>
/*!
* MainBoard父類
*
* @since V1.0
*/
@interface MainBoardBase : NSObject
@property int cpuHoles;//CPU插槽數
-(void)installCpuHoles;//統計CPU插槽數
@end
Intel的主機闆子類:
#import "MainBoardBase.h"
/*!
* Intel的主機闆子類
*
* @since V1.0
*/
@interface IntelMainBoard : MainBoardBase
@end
工廠基類:
#import <Foundation/Foundation.h>
#import "CpuBase.h"
#import "MainBoardBase.h"
/*!
* 工廠基類
*
* @since V1.0
*/
@interface FactoryBase : NSObject
/*!
* 建立CPU
* @return 傳回CPU執行個體
*
* @since V1.0
*/
-(CpuBase*)createCpu;
/*!
* 建立主機闆
*
* @return 傳回主機闆執行個體
*
* @since V1.0
*/
-(MainBoardBase*)createMainBoard;
@end
Intel工廠子類:
#import "FactoryBase.h"
#import "IntelCPU.h"
#import "IntelMainBoard.h"
/*!
* Intel工廠子類
*
* @since V1.0
*/
@interface IntelFactory : FactoryBase
@end
電腦工程師類:
#import <Foundation/Foundation.h>
#import "CpuBase.h"
#import "MainBoardBase.h"
#import "FactoryBase.h"
/*!
* 電腦工程師類
*
* @since V1.0
*/
@interface ComputerEngineer : NSObject
@property(nonatomic,retain)CpuBase* cpu;//CPU基類
@property(nonatomic,retain)MainBoardBase* mainBoard;//主機闆基類
-(void)makeComputer:(FactoryBase*)factoryBase;
/*!
* 組裝硬體
*
* @param factoryBase 工廠基類
*
* @since V1.0
*/
-(void)prepareHardwares:(FactoryBase*)factoryBase;
@end
用戶端類:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//建立裝機工程師對象
ComputerEngineer* cf = [[ComputerEngineer alloc] init];
//客戶選擇并建立需要使用的産品對象
FactoryBase* af = [[IntelFactory alloc] init];
// FactoryBase* af = [[AMDFactory alloc] init];
//告訴裝機工程師自己選擇的産品,讓裝機工程師組裝電腦
[cf makeComputer:af];
}
3 結語
以上是所有内容,希望對大家有所幫助。
執行個體代碼下載下傳位址:http://download.csdn.net/detail/u010013695/6946281