
這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。
在工廠模式中,我們在創(chuàng)建對象時(shí)不會(huì)對客戶端暴露創(chuàng)建邏輯,并且是通過使用一個(gè)共同的接口(協(xié)議)來指向新創(chuàng)建的對象。
(一)簡單工廠:
建模:

Step 1:
配置項(xiàng)目中用到的高德地圖和百度地圖,請參照官方文檔自行配置,這里不再闡述。
Step 2:
創(chuàng)建簡單工廠類 MapFactory ,定義地圖類型枚舉。
typedef NS_ENUM(NSInteger, MapType) {
MapTypeWithGaode, // 高德地圖
MapTypeWithBaidu, // 百度地圖
};
在 MapFactory.h 中定義兩個(gè)方法:
/**
配置地圖
@param type 地圖類型
*/
- (instancetype)initWithType:(MapType)type;
/**
返回一個(gè)地圖對象
@param frame frame
@return 地圖實(shí)例
*/
- (UIView *)getMapViewWithFrame:(CGRect)frame;
Step 3: 導(dǎo)入地圖頭文件,實(shí)現(xiàn) MapFactory .m
// 高德地圖
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <MAMapKit/MAMapKit.h>
// 百度地圖
#import <BaiduMapAPI_Base/BMKBaseComponent.h>
#import <BaiduMapAPI_Map/BMKMapComponent.h>
@interface MapFactory()
/** 地圖類型 */
@property(nonatomic,assign) MapType mapType;
/** 地圖 */
@property(nonatomic,strong) UIView *mapView;
@end
@implementation MapFactory
- (instancetype)initWithType:(MapType)type {
self = [super init];
if (self) {
_mapType = type;
if (_mapType == MapTypeWithGaode) {
[AMapServices sharedServices].apiKey = @"cf67bbca16a71b941da1df07550cc526";
} else if (_mapType == MapTypeWithBaidu) {
BMKMapManager* _mapManager = [[BMKMapManager alloc] init];
BOOL ret = [_mapManager start:@"UfT4LGMjKAOB8fWL540hrslg2xVIfiUW" generalDelegate:nil];
if (!ret) {
NSLog(@"manager start failed!");
}
}
}
return self;
}
- (UIView *)getMapViewWithFrame:(CGRect)frame {
if (_mapType == MapTypeWithGaode) {
_mapView = [[MAMapView alloc] initWithFrame:frame];
} else if (_mapType == MapTypeWithBaidu) {
_mapView = [[BMKMapView alloc]initWithFrame:frame];
}
return _mapView;
}
Step 4: 簡單工廠的使用
在需要使用地圖的 controller 中,#import "MapFactory.h"
// 修改type即可實(shí)現(xiàn)地圖的切換
MapFactory *factory = [[MapFactory alloc] initWithType:MapTypeWithGaode];
UIView *mapView = [factory getMapViewWithFrame:self.view.bounds];
[self.view addSubview:mapView];
效果如下:

(二)工廠方法:
在簡單工廠的基礎(chǔ)之上進(jìn)行了抽象(protocol).
定義一個(gè)用于創(chuàng)建對象的統(tǒng)一接口(protocol),然后由子類實(shí)現(xiàn)。
建模:

Step 1:
根據(jù)模型創(chuàng)建工廠方法協(xié)議 IComputerFactory 和 IComputer protocol。

// IComputerFactory
#import <Foundation/Foundation.h>
#import "IComputer.h"
@protocol IComputerFactory <NSObject>
- (id<IComputer>)getComputer;
@end
// IComputer
#import <Foundation/Foundation.h>
@protocol IComputer <NSObject>
- (void)printInfo;
@end
Step 2:
創(chuàng)建遵循 <IComputerFactory> 協(xié)議的電腦工廠類 AppleComputerFactory ,并實(shí)現(xiàn)協(xié)議方法。
// .h
#import <Foundation/Foundation.h>
#import "IComputerFactory.h"
// 蘋果電腦工廠 -> 遵循電腦工廠協(xié)議<IComputerFactory>
@interface AppleComputerFactory : NSObject<IComputerFactory>
@end
// .m
#import "AppleComputerFactory.h"
#import "AppleComputer.h"
@implementation AppleComputerFactory
// 返回具體的電腦
- (id<IComputer>)getComputer {
return [[AppleComputer alloc] init];
}
@end
Step 3:
創(chuàng)建遵循 <IComputer> 協(xié)議的電腦類 AppleComputer ,并實(shí)現(xiàn)協(xié)議方法。
// .h
#import <Foundation/Foundation.h>
#import "IComputer.h"
// 蘋果電腦 -> 遵循電腦協(xié)議<IComputer>
@interface AppleComputer : NSObject<IComputer>
@end
// .m
#import "AppleComputer.h"
@implementation AppleComputer
- (void)printInfo {
NSLog(@"生產(chǎn)了一臺處理器為2.9 GHz,內(nèi)存 8GB的蘋果電腦");
}
@end
Step 4:
在需要使用的地方,#import "AppleComputerFactory.h"
id<IComputerFactory> factory = [[AppleComputerFactory alloc] init];
id<IComputer> computer = [factory getComputer];
[computer printInfo];
控制臺效果:
通過簡單工廠和工廠方法的對比,大家有沒有發(fā)現(xiàn)簡單工廠的一些弊端呢?
- 拓展性比較差,都在一個(gè)類中,不便于多人協(xié)同開發(fā);
- 代碼冗余,耦合度比較高;
當(dāng)然了,沒有絕對完美的設(shè)計(jì)模式,只有適合的設(shè)計(jì)模式。我們需要根據(jù)實(shí)際項(xiàng)目需求采用合理的設(shè)計(jì)模式。
我在demo中的 FactoryMethod-Map 文件夾下實(shí)現(xiàn)了地圖的工廠方法,感興趣的可以在文章底部下載代碼查看。
(三)抽象工廠:
在工廠方法之上進(jìn)行了再次抽象(protocol).
為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個(gè)接口(protocol),而且無需指定他們的具體類。
抽象工廠和工廠方法的區(qū)別:
- 抽象工廠是為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個(gè)接口(protocol),工廠方法是一個(gè);
建模:

Step 1:
根據(jù)模型創(chuàng)建抽象工廠協(xié)議 IAbsComputerFactory 、 IAbsComputerGraphicsCard 和 IAbsComputerCpu protocol。

// IAbsComputerFactory
#import <Foundation/Foundation.h>
#import "IAbsComputerCpu.h"
#import "IAbsComputerGraphicsCard.h"
// 抽象工廠 電腦統(tǒng)一的抽象接口
@protocol IAbsComputerFactory <NSObject>
// CPU
- (id<IAbsComputerCpu>)getCpu;
// 顯卡
- (id<IAbsComputerGraphicsCard>)getGraphicsCard;
@end
// IAbsComputerGraphicsCard
#import <Foundation/Foundation.h>
// 抽象電腦顯卡接口
@protocol IAbsComputerGraphicsCard <NSObject>
// 打印電腦顯卡信息
- (void)printInfo;
@end
// IAbsComputerCpu
#import <Foundation/Foundation.h>
// 抽象電腦Cpu接口
@protocol IAbsComputerCpu <NSObject>
// 打印電腦Cpu信息
- (void)printInfo;
@end
Step 2:
創(chuàng)建遵循 <IAbsComputerFactory> 協(xié)議的電腦工廠類 AbsAppleComputerFactory ,并實(shí)現(xiàn)協(xié)議方法。
// .h
#import <Foundation/Foundation.h>
#import "IAbsComputerFactory.h"
// 遵循協(xié)議 <IAbsComputerFactory> 的實(shí)現(xiàn)類
@interface AbsAppleComputerFactory : NSObject<IAbsComputerFactory>
@end
// .m
#import "AbsAppleComputerFactory.h"
#import "AbsAppleComputerGraphicsCard.h"
#import "AbsAppleComputerCpu.h"
@implementation AbsAppleComputerFactory
// CPU
- (id<IAbsComputerCpu>)getCpu {
return [[AbsAppleComputerCpu alloc] init];
}
// 顯卡
- (id<IAbsComputerGraphicsCard>)getGraphicsCard {
return [[AbsAppleComputerGraphicsCard alloc] init];
}
@end
Step 3:
創(chuàng)建遵循 <IAbsComputerCpu> 協(xié)議的實(shí)現(xiàn)類 AbsAppleComputerCpu ,并實(shí)現(xiàn)協(xié)議方法。
// .h
#import <Foundation/Foundation.h>
#import "IAbsComputerCpu.h"
// 遵循協(xié)議 <IAbsComputerCpu> 的實(shí)現(xiàn)類
@interface AbsAppleComputerCpu : NSObject<IAbsComputerCpu>
@end
// .m
#import "AbsAppleComputerCpu.h"
@implementation AbsAppleComputerCpu
- (void)printInfo {
NSLog(@"生產(chǎn)了一個(gè)蘋果電腦的CPU。");
}
@end
Step 4:
創(chuàng)建遵循 <IAbsComputerGraphicsCard> 協(xié)議的實(shí)現(xiàn)類 AbsAppleComputerGraphicsCard ,并實(shí)現(xiàn)協(xié)議方法。
// .h
#import <Foundation/Foundation.h>
#import "IAbsComputerGraphicsCard.h"
// 遵循協(xié)議 <IAbsComputerGraphicsCard> 的實(shí)現(xiàn)類
@interface AbsAppleComputerGraphicsCard : NSObject<IAbsComputerGraphicsCard>
@end
// .m
#import "AbsAppleComputerGraphicsCard.h"
@implementation AbsAppleComputerGraphicsCard
- (void)printInfo {
NSLog(@"生產(chǎn)了一個(gè)蘋果電腦的顯卡。");
}
@end
Step 5:
在需要使用的地方,#import "AbsAppleComputerFactory.h"
id<IAbsComputerFactory> factory = [[AbsAppleComputerFactory alloc] init];
id<IAbsComputerCpu> cpu = [factory getCpu];
[cpu printInfo];
id<IAbsComputerGraphicsCard> graphicsCard = [factory getGraphicsCard];
[graphicsCard printInfo];
控制臺效果:
生產(chǎn)聯(lián)想電腦的類與上面所述的蘋果類如出一轍,這里就不再闡述了。如果以后要拓展其他電腦類,只需要按照這種模式實(shí)現(xiàn)就可以了,簡直不要太方便~
demo放在GitHub上了,想查看的小伙伴可以->戳這里。
千里之行,始于足下。