iOS開發(fā)之工廠模式 (Factory Pattern)

這種類型的設(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é)議 IComputerFactoryIComputer 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 、 IAbsComputerGraphicsCardIAbsComputerCpu 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上了,想查看的小伙伴可以->戳這里。


千里之行,始于足下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容