-
工廠方法
其實我也想著
有一天程序員做不下去了
頭發(fā)也掉光了
就回老家
老婆孩子熱炕頭的
開一家花生油店
畢竟家里祖?zhèn)鞯氖炙嚥荒軄G
這樣的話, 我首先就需要一個生產(chǎn)花生油實例的花生油類 : HXPeanutOil :
//HXPeanutOil.h
#import <Foundation/Foundation.h>
@interface HXPeanutOil : NSObject
- (void)smellSmell;
@end
// HXPeanutOil.m
#import "HXPeanutOil.h"
@implementation HXPeanutOil
- (void)smellSmell {
NSLog(@"我是花生油, 我是花生油的味道");
}
@end
當然想要生產(chǎn)花生油
得有個小作坊, 也就是工廠
// HXPeanutOilFactory.h
#import <Foundation/Foundation.h>
#import "HXPeanutOil.h"
@interface HXPeanutOilFactory : NSObject
+ (HXPeanutOil *)createOil;
@end
// HXPeanutOilFactory.m
#import "HXPeanutOilFactory.h"
@implementation HXPeanutOilFactory
+ (HXPeanutOil *)createOil {
return [[HXPeanutOil alloc] init];
}
@end
這樣基本就可以開工了
但是!
作為一個頭發(fā)都禿光了的資深程序員
怎么能如此目光短淺
只生產(chǎn)花生油呢
哪天客戶要我生產(chǎn)玉米油咋整
學以致用
繼承搞起來
多態(tài)搞起來
于是
抽象工廠就誕生了 :
// HXOilFactory.h
#import <Foundation/Foundation.h>
#import "HXOil.h"
@interface HXOilFactory : NSObject
+ (HXOil *)createOil;
@end
// HXOilFactory.m
#import "HXOilFactory.h"
@implementation HXOilFactory
+ (HXOil *)createOil {
return nil;
}
@end
于是
抽象產(chǎn)品也就誕生了 :
// HXOil.h
#import <Foundation/Foundation.h>
@interface HXOil : NSObject
- (void)smellSmell;
@end
// HXOil.m
#import "HXOil.h"
@implementation HXOil
- (void)smellSmell {
}
@end
讓之前花生油工廠 HXPeanutOilFactory 繼承抽象工廠 HXOilFactory, 并把的生產(chǎn)操作 createOil 提取到父類
讓之前花生油產(chǎn)品 HXPeanutOil 繼承抽象產(chǎn)品 HXOil, 并把的聞一聞操作 smellSmell 提取到父類
這樣的話, 看起來舒適很多
如果這時候花生油生意做大了
出于對我產(chǎn)油能力的肯定, 客戶非要我生產(chǎn)玉米油
這樣的話玉米油工廠只需要繼承 HXOilFactory 創(chuàng)建 HXMaizeOilFactory
公用的生產(chǎn)操作已經(jīng)在父類中聲明
// HXMaizeOilFactory.h
#import "HXOilFactory.h"
@interface HXMaizeOilFactory : HXOilFactory
@end
// HXMaizeOilFactory.m
#import "HXMaizeOilFactory.h"
#import "HXMaizeOil.h"
@implementation HXMaizeOilFactory
+ (HXMaizeOil *)createOil {
return [[HXMaizeOil alloc] init];
}
@end
然后玉米油就是繼承 HXOil 的 HXMaizeOil
同樣公用的聞一聞操作也已經(jīng)在父類中已經(jīng)聲明
// HXMaizeOil.h
#import "HXOil.h"
@interface HXMaizeOil : HXOil
@end
// HXMaizeOil.m
#import "HXMaizeOil.h"
@implementation HXMaizeOil
- (void)smellSmell {
NSLog(@"我是玉米油, 我是玉米油的味道");
}
@end
這樣以來
就可以完美的生產(chǎn)出玉米油
客戶只需要像讓我生產(chǎn)花生油那樣
告訴我生產(chǎn)玉米油
就可以生產(chǎn)玉米油了
不需要客戶端做額外操作
如果客戶有一天覺得這些油都不好吃了
想嘗一嘗地溝油
那么只需要繼承 HXOilFactory 創(chuàng)建地溝油工廠類
繼承 HXOil 創(chuàng)建地溝油產(chǎn)品類
就可以生產(chǎn)地溝油給客戶啦
例如生產(chǎn)玉米油, 大概就像這個樣子 :
- (void)createMaizeOil {
HXOil *oil = [HXMaizeOilFactory createOil];
[oil smellmell];
}
總結(jié) :
工廠方法模式中的參與者:
抽象工廠角色:工廠模式的基類,定義了公共接口
具體工廠角色:實現(xiàn)了抽象工廠類的接口,是與客戶端直接交互的類,負責具體的產(chǎn)品對象的創(chuàng)建
抽象產(chǎn)品角色:是具體產(chǎn)品類的基類,定義了公共接口
具體產(chǎn)品角色:實現(xiàn)了抽象產(chǎn)品類接口,每一個具體產(chǎn)品類都會對應一個工廠
-
抽象工廠
發(fā)現(xiàn)回到家之后
油坊火了
實現(xiàn)財富自由了
沒辦法啊,怎么辦呢?
創(chuàng)品牌吧!
品牌就叫擼花花生油
然后又給自己的品牌設計了
一個個性油桶和一個個性 Logo
油桶和 Logo 哪里來?
自產(chǎn)!
要生產(chǎn)油桶和 Logo
也得要工廠啊
瞅了瞅自己的花生油玉米油和地溝油的油廠
油廠只能生產(chǎn)油
想讓油廠產(chǎn)油桶和 logo 估計也不好使
重新建廠! 有錢!
軟件設計的黃金法則 : 變動需要抽象!
于是抽象工廠 HXOilAccessoryFactory 類誕生了 :
// HXOilAccessoryFactory.h
#import <Foundation/Foundation.h>
#import "HXOilLogo.h"
#import "HXOilContainer.h"
typedef NS_ENUM(NSUInteger, HXOilType) {
/** 擼花花生油 */
HXOilTypeLuHuaOil
};
@interface HXOilAccessoryFactory : NSObject
+ (HXOilAccessoryFactory *)factoryWithType:(HXOilType)type;
- (HXOilLogo *)createOilLogo;
- (HXOilContainer *)createilContainer;
@end
// HXOilAccessoryFactory.m
#import "HXOilAccessoryFactory.h"
#import "HXLuHuaOilAccessoryFactory.h"
@implementation HXOilAccessoryFactory
+ (HXOilAccessoryFactory *)factoryWithType:(HXOilType)type {
if (type == HXOilTypeLuHuaOil) {
return [[HXLuHuaOilAccessoryFactory alloc] init];
}else {
return nil;
}
}
- (HXOilLogo *)createOilLogo {
return nil;
}
- (HXOilContainer *)createilContainer {
return nil;
}
@end
這個類干這么2件事 :
根據(jù)客戶需求, 返回具體工廠
聲明了每個具體工廠都需要實現(xiàn)的接口(生產(chǎn) Logo 接口,和生產(chǎn)油桶接口)
然后就是我們創(chuàng)的品牌擼花花生油的具體工廠
繼承自 HXOilAccessoryFactory 的 HXLuHuaOilAccessoryFactory
// HXLuHuaOilAccessoryFactory.h
#import "HXOilAccessoryFactory.h"
@interface HXLuHuaOilAccessoryFactory : HXOilAccessoryFactory
@end
// HXLuHuaOilAccessoryFactory.m
#import "HXLuHuaOilAccessoryFactory.h"
#import "HXLuHuaOilLogo.h"
#import "HXLuHuaOilContainer.h"
@implementation HXLuHuaOilAccessoryFactory
- (HXOilLogo *)createOilLogo {
return [[HXLuHuaOilLogo alloc] init];
}
- (HXOilContainer *)createilContainer {
return [[HXLuHuaOilContainer alloc] init];
}
@end
他用來生產(chǎn)實體 Logo 和實體油桶
生產(chǎn)出的油桶是 HXLuHuaOilContainer
Logo 就是 HXLuHuaOilLogo
HXLuHuaOilContainer 繼承抽象產(chǎn)品類 HXOilContainer
HXLuHuaOilLogo 繼承抽象產(chǎn)品類 HXOilLogo
他們的實現(xiàn)分別如下 :
// HXOilLogo.h
// Logo 的抽象父類
#import <Foundation/Foundation.h>
@interface HXOilLogo : NSObject
- (void)color;
- (void)appearance;
@end
// HXOilLogo.m
#import "HXOilLogo.h"
@implementation HXOilLogo
- (void)color {
}
- (void)appearance {
}
@end
// HXLuHuaOilLogo.h
// 我是擼花花生油 Logo 的實體類
#import "HXOilLogo.h"
@interface HXLuHuaOilLogo : HXOilLogo
@end
// HXLuHuaOilLogo.m
#import "HXLuHuaOilLogo.h"
@implementation HXLuHuaOilLogo
- (void)color {
NSLog(@"我是擼花花生油 Logo, 我是黃色");
}
- (void)appearance {
NSLog(@"我是擼花花生油 Logo, 我是三角形");
}
@end
// HXOilContainer.h
// 油桶 OilContainer 的抽象父類
#import <Foundation/Foundation.h>
@interface HXOilContainer : NSObject
- (void)name;
- (void)size;
@end
// HXOilContainer.m
#import "HXOilContainer.h"
@implementation HXOilContainer
- (void)name {
}
- (void)size {
}
@end
// HXLuHuaOilContainer.h
// 擼花花生油的油桶實體類
#import "HXOilContainer.h"
@interface HXLuHuaOilContainer : HXOilContainer
@end
// HXLuHuaOilContainer.m
#import "HXLuHuaOilContainer.h"
@implementation HXLuHuaOilContainer
- (void)name {
NSLog(@"我是擼花花生油油桶");
}
- (void)size {
NSLog(@"我是擼花花生油油桶 -- 我能裝3L");
}
@end
對于 Logo
他有 color 和 appearance 兩個操作
都已在抽象父類中聲明
實體子類來具體實現(xiàn)
對于 OilContainer
他有 name 和 size 兩個操作
都已在抽象父類中聲明
實體子類來具體實現(xiàn)
客戶端的調(diào)用 :
- (void)abstractFactory {
HXOilAccessoryFactory *factory = [HXOilAccessoryFactory factoryWithType:HXOilTypeLuHuaOil];
HXOilLogo *logo = [factory createOilLogo];
HXOilContainer *container = [factory createilContainer];
[logo color];
[logo appearance];
[container name];
[container size];
}
打印是這個樣子 :
2018-08-07 16:25:40.115446+0800 我是擼花花生油 Logo, 我是黃色
2018-08-07 16:25:40.115597+0800 我是擼花花生油 Logo, 我是三角形
2018-08-07 16:25:40.115894+0800 我是擼花花生油油桶
2018-08-07 16:25:40.115974+0800 我是擼花花生油油桶 -- 我能裝3L
到此為止
已經(jīng)可以完美的生產(chǎn)擼花花生油的 Logo 和油桶(OilContainer)了
可是久而久之
客戶吃夠了擼花花生油
沒辦法, 他們總是喜新厭舊的
然后客戶提出了新需求 : 我還是想吃地溝油
怎么辦呢?
產(chǎn)啊, 地溝油油桶, 地溝油 Logo 都要產(chǎn)
先建廠 HXDiGouOilAccessoryFactory 繼承自剛才的抽象工廠 HXOilAccessoryFactory
// HXDiGouOilAccessoryFactory.h
#import "HXOilAccessoryFactory.h"
@interface HXDiGouOilAccessoryFactory : HXOilAccessoryFactory
@end
// HXDiGouOilAccessoryFactory.m
#import "HXDiGouOilAccessoryFactory.h"
#import "HXDiGouOilLogo.h"
#import "HXDiGouOilContainer.h"
@implementation HXDiGouOilAccessoryFactory
- (HXOilLogo *)createOilLogo {
return [[HXDiGouOilLogo alloc] init];
}
- (HXOilContainer *)createilContainer {
return [[HXDiGouOilContainer alloc] init];
}
@end
然后創(chuàng)建產(chǎn)品 HXDiGouOilLogo 繼承自 HXOilLogo
然后創(chuàng)建產(chǎn)品 HXDiGouOilContainer 繼承自 HXOilContainer
實現(xiàn)如下 ;
// HXDiGouOilLogo.h
// 我是地溝油 Logo
#import "HXOilLogo.h"
@interface HXDiGouOilLogo : HXOilLogo
@end
// HXDiGouOilLogo.m
#import "HXDiGouOilLogo.h"
@implementation HXDiGouOilLogo
- (void)color {
NSLog(@"我是地溝油 Logo, 我是棕色");
}
- (void)appearance {
NSLog(@"我是地溝油 Logo, 我是心形");
}
@end
// HXDiGouOilContainer.h
// 地溝油的油桶
#import "HXOilContainer.h"
@interface HXDiGouOilContainer : HXOilContainer
@end
// HXDiGouOilContainer.m
#import "HXDiGouOilContainer.h"
@implementation HXDiGouOilContainer
- (void)name {
NSLog(@"我是地溝油油桶");
}
- (void)size {
NSLog(@"我是地溝油油桶 -- 我能裝50L");
}
@end
調(diào)用的話 就可以這么搞 :
//抽象工廠
- (void)abstractFactory {
HXOilAccessoryFactory *factory = [HXOilAccessoryFactory factoryWithType:HXOilTypeDiGouOil];
HXOilLogo *logo = [factory createOilLogo];
HXOilContainer *container = [factory createilContainer];
[logo color];
[logo appearance];
[container name];
[container size];
}
打印將是這樣 :
2018-08-07 16:53:18.718973+0800 我是地溝油 Logo, 我是棕色
2018-08-07 16:53:18.719095+0800 我是地溝油 Logo, 我是心形
2018-08-07 16:53:18.719209+0800 我是地溝油油桶
2018-08-07 16:53:18.719333+0800 我是地溝油油桶 -- 我能裝50L
到這里為止
已經(jīng)可以完美的生產(chǎn)地溝油
滿足了客戶想吃地溝油的心情
思路大概就是這樣
以后增加新品種
就建新廠
搞新產(chǎn)品
抽象工廠的總結(jié)以及與工廠方法的區(qū)別 :
抽象工廠模式提供一個創(chuàng)建一系列相關或相互依賴的對象的接口
而無需指定它們具體的類(就像我們創(chuàng)建的具體工廠實例, 都是用抽象工廠的指針指向他, 其實指針并不知道自己指向的是地溝油實例, 還是花生油實例)
那么工廠模式和抽象工廠模式的區(qū)別是什么呢?
這兩種設計模式主要的區(qū)別在于產(chǎn)品
工廠模式是用來創(chuàng)建同一個產(chǎn)品的不同類型
比如說產(chǎn)油, 花生油, 玉米油, 地溝油, 都是油
但是抽象工廠模式是用來創(chuàng)建一系列相關不同類型的產(chǎn)品
比如油坊還想自己產(chǎn)一些 Logo 和油桶
剛才創(chuàng)建的油廠就不能產(chǎn)這些東西了, 就要重新建廠
一般來說,產(chǎn)品種類單一,適合用工廠模式
如果有多個種類,各種類型時,通過抽象工廠模式來進行創(chuàng)建是很合適的。
這里是代碼
我理解的有點糙
有不對的地方, 還望大神指正
感謝閱讀
你的支持是我寫作的唯一動力