抽象工廠模式

抽象工廠模式搏色,提供一個創(chuàng)建一系列相關(guān)或相互依賴的接口

優(yōu)點:

  • 易于交換產(chǎn)品系列
  • 讓具體的創(chuàng)建實例過程與客戶端分離,客戶端是通過他們的抽象接口操縱實例嗦玖,產(chǎn)品的具體類名也被具體工廠的實現(xiàn)分離,不會出現(xiàn)在客戶端代碼中

用戶類 User

///===================User.h=================
/// 用戶類
@interface User : NSObject

/// 用戶 id
@property (nonatomic, copy) NSString *userId;

/// 用戶名
@property (nonatomic, copy) NSString *username;

@end

/// ===============User.m===================
@implementation User

@end

部門類 Department

///===============Department.h===========
/// 部門類

@interface Department : NSObject

/// 部門 id
@property (nonatomic, copy) NSString *departmentId;

/// 部門名稱
@property (nonatomic, copy) NSString *departmentName;

@end

@implementation Department

@end

用于訪問用戶的接口 IUser

/// 用于訪問用戶的接口
@protocol IUser <NSObject>

/// 新增用戶
/// @param user 用戶對象
- (void)insert:(User *)user;

/// 獲取用戶
/// @param userId 用戶 id
/// @return 用戶對象
- (User *)getUser:(NSString *)userId;

@end

用于訪問 SQL Server 中的用戶 SQLServer

///==============SQLServerUser.h===========
/// 用于訪問 SQL Server 中的用戶
@interface SQLServerUser : NSObject <IUser>

@end


///==============SQLServerUser.m============
@implementation SQLServerUser

- (void)insert:(User *)user {
    NSLog(@"在 SQL Server 中給 User 表增加一條記錄");
}

- (User *)getUser:(NSString *)userId {
    NSLog(@"在 SQL Server 中根據(jù) userId 得到 User 表一條記錄");
    return nil;
}

@end

用于訪問 Access 中的用戶AccessUser

///=============AccessUser.h==============
/// 用于訪問 Access 中的用戶
@interface AccessUser : NSObject <IUser>

@end

///=============AccessUser.m==========
@implementation AccessUser

- (void)insert:(User *)user {
    NSLog(@"在 Access 中給 User 表增加一條記錄");
}

- (User *)getUser:(NSString *)userId {
    NSLog(@"在 Access 中根據(jù) userId 得到 User 表一條記錄");
    return nil;
}

@end

用于訪問部門的接口IDepartment

/// 用于訪問部門的接口
@protocol IDepartment <NSObject>

/// 新增部門
///
/// @param department 部門對象
- (void)insert:(Department *)department;

/// 獲取部門
///
/// @param departmentId 部門 id
///
/// @return 部門對象
- (Department *)getDepartment:(NSString *)departmentId;

@end

用于訪問 SQL Server 中的部門SQLServerDepartment

///==============SQLServerDepartment.h=========
/// 用于訪問 SQL Server 中的部門
@interface SQLServerDepartment : NSObject <IDepartment>

@end

///==============SQLServerDepartment.m=========
@implementation SQLServerDepartment

- (void)insert:(Department *)department {
    NSLog(@"在 SQL Server 中給 Department 表增加一條記錄");
}

- (Department *)getDepartment:(NSString *)departmentId {
    NSLog(@"在 SQL Server 中根據(jù) departmentId 得到 Department 表一條記錄");
    return nil;
}

用于訪問 Access 中的部門 AccessDepartment

///=============AccessDepartment.h===========
/// 用于訪問 Access 中的部門
@interface AccessDepartment : NSObject <IDepartment>

@end


=============AccessDepartment.h===========
@implementation AccessDepartment

- (void)insert:(Department *)department {
    NSLog(@"在 Access 中給 Department 表增加一條記錄");
}

- (Department *)getDepartment:(NSString *)departmentId {
    NSLog(@"在 Access 中根據(jù) departmentId 得到 Department 表一條記錄");
    return nil;
}

@end

抽象工廠接口IFactory.h

/// 抽象工廠接口
@protocol IFactory <NSObject>

/// 創(chuàng)建用于訪問用戶的對象
///
/// @return 用于訪問用戶的對象
- (id<IUser>)createUser;

/// 創(chuàng)建用于訪問部門的對象
///
/// @return 用于訪問部門的對象
- (id<IDepartment>)createDepartment;

@end

創(chuàng)建用于訪問 SQL Server 對象的工廠類SQLServerFactory

///==============SQLServerFactory.h============
/// 創(chuàng)建用于訪問 SQL Server 對象的工廠類
@interface SQLServerFactory : NSObject <IFactory>

@end


///==============SQLServerFactory.m============
@implementation SQLServerFactory

- (id<IUser>)createUser {
    return [[SQLServerUser alloc] init];
}

- (id<IDepartment>)createDepartment {
    return [[SQLServerDepartment alloc] init];
}

@end

創(chuàng)建用于訪問 Access 對象的工廠類 AccessFactory

/// ================AccessFactory.h==========
/// 創(chuàng)建用于訪問 Access 對象的工廠類
@interface AccessFactory : NSObject <IFactory>

@end

/// ================AccessFactory.m==========
@implementation AccessFactory

- (id<IUser>)createUser {
    return [[AccessUser alloc] init];
}

- (id<IDepartment>)createDepartment {
    return [[AccessDepartment alloc] init];
}

@end

類圖

抽象工廠模式.png

AbstractProductA 和 AbstractProductB 是兩個抽象產(chǎn)品, 只定義了接口谴麦,可以有不同的實現(xiàn)方式, 先相當于User 和 Department, ProductA1狭瞎、 ProductA2细移、 ProductB1 ProductB2就是對兩個抽象產(chǎn)品的實現(xiàn)
同理, IFactory 是一個抽象接口熊锭,它里面應(yīng)該包含所有產(chǎn)品的創(chuàng)建的抽象方法, ConcreteFactory1 ConcreteFactory2 就是具體工廠
通常實在運行時刻再創(chuàng)建一個ConcreteFactory類的實例弧轧,這個具體的工廠再創(chuàng)建具有特定實現(xiàn)的產(chǎn)品對象, 也就是說碗殷, 為創(chuàng)建不同的產(chǎn)品對象精绎,客戶端使用不同的具體工廠

抽象工廠與工廠方法比較

抽象工廠 工廠方法
通過對象組合創(chuàng)建抽象產(chǎn)品 通過類繼承創(chuàng)建抽象產(chǎn)品
創(chuàng)建多系列產(chǎn)品 創(chuàng)建一種產(chǎn)品
必須修改父類接口才能支持新的產(chǎn)品 子類化創(chuàng)建者并重載工廠方法以創(chuàng)建新產(chǎn)品

iOS中的抽象工廠

在iOS中,有很多基礎(chǔ)類采用了這一模式锌妻,常見的就是NSNumber代乃。創(chuàng)建NSNumber實例的方法完全符合抽象工廠模式

NSNumber *boolNumber = [NSNumber numberWithBool:YES];
NSNumber *charNumber = [NSNumber numberWithChar:'a'];
NSNumber *intNumber = [NSNumber numberWithInt:1];
NSNumber *floatNumber = [NSNumber numberWithFloat:1.0];
NSNumber *doubleNumber = [NSNumber numberWithDouble:1.0];

接受不同類型的參數(shù)并返回NSNumber實例的類方法是類工廠方法(工廠模式)。NSNumber的類工廠方法生產(chǎn)各種數(shù)工廠。numberWithBool:創(chuàng)建NSCFBoolean工廠的實例搁吓,而numberWithInt:創(chuàng)建NSCFNumber的實例原茅。NSNumber中的類工廠方法定義了決定實例化何種私有具體子類(比
如,NSCFBooleanNSCFNumber)的默認行為堕仔。這一版本的工廠方法是傳統(tǒng)工廠方法模式的一個變體擂橘,此處的抽象產(chǎn)品為作為工廠的具體
NSNumber子類。NSNumber是抽象工廠實現(xiàn)的一個例子摩骨⊥ㄕ辏基礎(chǔ)框架中抽象工廠的此種特點被稱為類簇。
類簇是基礎(chǔ)框架中一種常見的設(shè)計模式恼五,基于抽象工廠模式的思想昌罩。它將若干相關(guān)的私有具體工廠子類集合到一個公有的抽象超類之下。比如灾馒,數(shù)包含了各種數(shù)值類型的完整集合茎用,如字符、浮點數(shù)你虹、整數(shù)等绘搞。這些數(shù)值類型都是數(shù)的子集。所以NSNumber自然成為這些數(shù)子類型的超類型傅物。NSNumber有一系列公有API夯辖,定義了各種類型的數(shù)所共有的行為《危客戶端在使用時無需知道NSNumber實例的具體類型蒿褂。
類簇是抽象工廠的一種形式。比如卒暂,NSNumber本身是一個高度抽象的工廠啄栓,NSCFBooleanNSCFNumber是具體工廠子類。子類是具體工廠也祠,因為它們重載了NSNumber中聲明的公有工廠方法以生產(chǎn)產(chǎn)品昙楚。
例如,intValueboolValue根據(jù)實際NSNumber對象的內(nèi)部值返回一個值诈嘿,雖然值的數(shù)據(jù)類型可能不同堪旧。從這些工廠方法返回的實際值就是抽象工廠模式的最初定義中的所說產(chǎn)品。
創(chuàng)建抽象產(chǎn)品的工廠方法與創(chuàng)建抽象工廠的工廠方法之間有個不同點奖亚。顯然淳梦,像intValueboolValue這樣的工廠方法,應(yīng)該在具體工廠(NSCFNumberNSCFBoolean)中重載以返回產(chǎn)品昔字。而像numberWithBool:numberWithInt:這樣的工廠方法并不是為了返回產(chǎn)品爆袍,而是為了返回能返回產(chǎn)品的工廠,因此它們不應(yīng)在具體子類重載。

總結(jié)

抽象工廠是一種常見的設(shè)計模式陨囊。它是最基本的弦疮,因為它可以設(shè)計許多類型的對象創(chuàng)建。一系列相關(guān)類好的設(shè)計模式谆扎,應(yīng)該作為一種抽象挂捅,不為客戶端所見。抽象工廠可以順暢地提供這種抽象堂湖,而不暴露創(chuàng)建過程中任何不必要的細節(jié)或所創(chuàng)建對象的確切類型。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末状土,一起剝皮案震驚了整個濱河市无蜂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蒙谓,老刑警劉巖斥季,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異累驮,居然都是意外死亡酣倾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門谤专,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躁锡,“玉大人,你說我怎么就攤上這事置侍∮持” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵蜡坊,是天一觀的道長杠输。 經(jīng)常有香客問我,道長秕衙,這世上最難降的妖魔是什么蠢甲? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮据忘,結(jié)果婚禮上鹦牛,老公的妹妹穿的比我還像新娘。我一直安慰自己若河,他們只是感情好能岩,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著萧福,像睡著了一般拉鹃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天膏燕,我揣著相機與錄音钥屈,去河邊找鬼。 笑死坝辫,一個胖子當著我的面吹牛篷就,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播近忙,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼竭业,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了及舍?” 一聲冷哼從身側(cè)響起未辆,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锯玛,沒想到半個月后咐柜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡攘残,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年拙友,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歼郭。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遗契,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出实撒,到底是詐尸還是另有隱情姊途,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布知态,位于F島的核電站捷兰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏负敏。R本人自食惡果不足惜贡茅,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望其做。 院中可真熱鬧顶考,春花似錦、人聲如沸妖泄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹈胡。三九已至渊季,卻和暖如春朋蔫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背却汉。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工驯妄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人合砂。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓青扔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翩伪。 傳聞我的和親對象是個殘疾皇子微猖,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354