項目代碼結構優(yōu)化(工廠模式以及面向協(xié)議編程)

舉例提問

你有什么方法在項目中實現(xiàn)快速切換百度地圖高德地圖?(ps:本文例子是針對iOS項目講解的,但是思想是可以借鑒到其他語言中的。)
或許有不少朋友的答案是修改代碼唄竖瘾。
那么,我再給一個前提:如何在不改動客戶端代碼或者盡可能少量的修改代碼呢花颗?
今天捕传,我就帶大家來實現(xiàn)如何不改動客戶端代碼或者盡可能少量的修改客戶端代碼來實現(xiàn)項目中百度地圖高德地圖的快速切換。

集成百度地圖

先創(chuàng)建一個工程扩劝,然后將百度地圖sdk集成到項目庸论,(此處忽略集成步驟职辅,具體可以在百度地圖sdk接入文檔中查看)。在百度地圖官網(wǎng)申請appkey聂示,然后在AppDelegate初始化百度地圖域携,這篇文章我們只是簡單的使用一下百度地圖,在ViewController中我們導入#import <BaiduMapAPI_Map/BMKMapComponent.h>鱼喉,然后創(chuàng)建一個mapView添加到控制器上秀鞭,

#import "ViewController.h"
#import <BaiduMapAPI_Map/BMKMapComponent.h>

@interface ViewController ()

@property (nonatomic, strong) BMKMapView *mapView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.mapView = [[BMKMapView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:self.mapView];
}

運行我們的app,ok扛禽,不出意外的話锋边,我們界面上能夠正確的顯示百度地圖。(ps:問了項目結構看起來舒服编曼,這里分文件夾管理Framework下包含了GaodeMapBaiduMap兩個文件夾)

集成高度地圖

然后我們需要再集成高德地圖sdk到項目豆巨,申請appkey,然后在Appdelegate里面添加

[AMapServices sharedServices].apiKey = @"你的key";

同樣掐场,我們在ViewController中我們導入#import <MAMapKit/MAMapView.h>往扔,然后創(chuàng)建一個mapView添加到控制器上,

#import "ViewController.h"
// #import <BaiduMapAPI_Map/BMKMapComponent.h>
#import <MAMapKit/MAMapView.h>

@interface ViewController ()

// @property (nonatomic, strong) BMKMapView *mapView;
@property (nonatomic, strong) MAMapView *mMapView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // self.mapView = [[BMKMapView alloc] initWithFrame:self.view.bounds];
    // [self.view addSubview:self.mapView];
    
    self.mMapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:self.mMapView];
}

運行我們的代碼熊户,ok,我們也能愉快的看到界面上顯示的是高德地圖瓤球。

面向協(xié)議思想

通過以上的代碼,我們可以發(fā)現(xiàn)有兩個點:

  • 無論是BMKMapView還是MAMapView敏弃,他們都是繼承于UIView的。
  • 必須指定創(chuàng)建的位置和大小噪馏。

因此麦到,我們可以通過protocol來抽出他們的共性。

ok欠肾,我們在Framework文件夾下創(chuàng)建一個BaseMap文件夾,然后創(chuàng)建一個IMapViewProtocol的協(xié)議類瓶颠,然后將上述的兩個特點定義成兩個方法。

#import <UIKit/UIKit.h>

@protocol IMapViewProtocol <NSObject>

- (instancetype)initWithFrame:(CGRect)frame;

- (UIView *)getMapView;

@end

接下來刺桃,我們創(chuàng)建兩個類BaiduMapViewGaodeMapView并且這兩個類都實現(xiàn)IMapViewProtocol協(xié)議粹淋,因此需要實現(xiàn)協(xié)議方法。

  • BaiduMapView
#import "BaiduMapView.h"
#import <BaiduMapAPI_Map/BMKMapComponent.h>

@interface BaiduMapView ()

@property (nonatomic, strong) BMKMapView *mapView;

@end

@implementation BaiduMapView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super init];
    if (self) {
        _mapView = [[BMKMapView alloc] initWithFrame:frame];
    }
    return self;
}

- (UIView *)getMapView {
    return _mapView;
}

@end
  • GaodeMapView
#import "GaodeMapView.h"
#import <MAMapKit/MAMapView.h>

@interface GaodeMapView ()
@property (nonatomic, strong) MAMapView *mapView;
@end

@implementation GaodeMapView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super init];
    if (self) {
        _mapView = [[MAMapView alloc] initWithFrame:frame];
    }
    return self;
}

- (UIView *)getMapView {
    return self.mapView;
}

@end

此時我們可以在ViewController里面添加如下代碼瑟慈。

#import "ViewController.h"
#import "BaiduMapView.h"
#import "GaodeMapView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    id<IMapViewProtocol> mapView = [[GaodeMapView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:[mapView getMapView]];
}

運行項目桃移,此時,我們可以看到界面上顯示出來高德地圖葛碧。(ps:在Appdelegate里面配置好高德地圖的key借杰,下面也是同理。)此時进泼,如果我們想要切換成百度地圖的時候蔗衡,我們只需要修改創(chuàng)建mapView對象的纤虽。

工廠模式

到現(xiàn)在為止,我們確實能夠盡可能少地修改代碼去切換兩個地圖的顯示了绞惦,可是逼纸,
假如我們一個項目中很多的地方用到了百度地圖或者高德地圖,那么我們是不是需要逐個逐個地去修改呢济蝉?這時候杰刽,我們就應該考慮使用工廠模式了,就好比生產(chǎn)衣服的工廠堆生,怎么生產(chǎn)的我們不知道专缠,其實我們也并不關心,我們只對其生產(chǎn)出來的結果感興趣淑仆。那么涝婉,我們應該將生產(chǎn)高德地圖的工廠和生產(chǎn)百度地圖的工廠分開呢,還是寫在一個工廠呢蔗怠?不用想墩弯,我們肯定是需要分開生產(chǎn)的。但是寞射,我們可以考慮到兩個工廠生產(chǎn)出來的實例有個共同點:

  • 生產(chǎn)出來的實例必須遵守<IMapViewProtocol>協(xié)議

因此渔工,我們可以定義一個協(xié)議類IMapFactoryProtocol

#import <UIKit/UIKit.h>
#import "IMapViewProtocol.h"

@protocol IMapFactoryProtocol <NSObject>

- (id<IMapViewProtocol>)getMapView:(CGRect)frame;

@end

然后定義兩個遵守<IMapViewProtocol>的工廠類:

  • BaiduMapFactory
#import "BaiduMapFactory.h"
#import "BaiduMapView.h"
#import <BaiduMapAPI_Base/BMKMapManager.h>

@interface BaiduMapFactory (){
    BMKMapManager *_mapManager;
}

@end

@implementation BaiduMapFactory

- (instancetype)init {
    self = [super init];
    if (self) {
        _mapManager = [[BMKMapManager alloc]init];
        // 如果要關注網(wǎng)絡及授權驗證事件,請設定     generalDelegate參數(shù)
        BOOL ret = [_mapManager start:@"xnbikl7G1GolppT27HKdgfd10jtqDd0G"  generalDelegate:nil];
        if (!ret) {
            NSLog(@"初始化失敗");
        }
    }
    return self;
}

- (id<IMapViewProtocol>)getMapView:(CGRect)frame {
    return [[BaiduMapView alloc] initWithFrame:frame];
}

@end
  • GaodeMapFactory
#import "GaodeMapFactory.h"
#import <AMapFoundationKit/AMapFoundationKit.h>
#import "GaodeMapView.h"

@implementation GaodeMapFactory

- (instancetype)init {
    self = [super init];
    if (self) {
        [AMapServices sharedServices].apiKey = @"fdbbc0bd9dc04f6b9922bf357ef1eaa8";
    }
    return self;
}

- (id<IMapViewProtocol>)getMapView:(CGRect)frame {
    return [[GaodeMapView alloc] initWithFrame:frame];
}

經(jīng)過上面的結構整理桥温,我們在定義一個引擎類----MapEngine

MapEngine.h

#import <Foundation/Foundation.h>
#import "IMapFactoryProtocol.h"

@interface MapEngine : NSObject
- (id<IMapFactoryProtocol>)getMapFactory;
@end

MapEngine.m:

#import "MapEngine.h"
#import "BaiduMapFactory.h"
#import "GaodeMapFactory.h"


@implementation MapEngine

- (id<IMapFactoryProtocol>)getMapFactory {
    return [[BaiduMapFactory alloc] init];
}

@end

好了引矩,到此為止,我們的結構優(yōu)化算是完成了侵浸。這時候旺韭,我們再回到ViewController中來看看我們的代碼。

#import "ViewController.h"
#import "IMapViewProtocol.h"
#import "MapEngine.h"

@interface ViewController ()

@property (nonatomic, strong) UIView *mMapView;
@property (nonatomic, strong) MapEngine *engine;
@property (nonatomic, strong) id<IMapFactoryProtocol> factory;
@property (nonatomic, strong) id<IMapViewProtocol> mapView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.engine = [[MapEngine alloc] init];
    self.factory = [self.engine getMapFactory];
    self.mapView = [self.factory getMapView:self.view.bounds];
    self.mMapView = [self.mapView getMapView];
    [self.view addSubview:self.mMapView];
}

現(xiàn)在掏觉,我們?nèi)绻胍袚Q地圖顯示区端,我們只需要在MapEngine類里面改變一下工廠類即可。這時候澳腹,我們甚至還可以接入服務器织盼,讓服務配合,可以不修改客戶端任何代碼就實現(xiàn)地圖切換了酱塔。

結尾

  • 如果您有更好的思路歡迎交流沥邻。
  • 如果您有發(fā)現(xiàn)錯誤或者有疑問的地方,歡迎交流羊娃,謝謝D惫!
  • 大神勿噴G芦瘾!
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捌蚊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子近弟,更是在濱河造成了極大的恐慌缅糟,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祷愉,死亡現(xiàn)場離奇詭異窗宦,居然都是意外死亡,警方通過查閱死者的電腦和手機二鳄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門赴涵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人订讼,你說我怎么就攤上這事髓窜。” “怎么了欺殿?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵寄纵,是天一觀的道長。 經(jīng)常有香客問我脖苏,道長程拭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任棍潘,我火速辦了婚禮恃鞋,結果婚禮上,老公的妹妹穿的比我還像新娘亦歉。我一直安慰自己恤浪,他們只是感情好,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布鳍徽。 她就那樣靜靜地躺著,像睡著了一般敢课。 火紅的嫁衣襯著肌膚如雪阶祭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天直秆,我揣著相機與錄音濒募,去河邊找鬼。 笑死圾结,一個胖子當著我的面吹牛瑰剃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筝野,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼晌姚,長吁一口氣:“原來是場噩夢啊……” “哼粤剧!你這毒婦竟也來了?” 一聲冷哼從身側響起挥唠,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤抵恋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宝磨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弧关,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年唤锉,在試婚紗的時候發(fā)現(xiàn)自己被綠了世囊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡窿祥,死狀恐怖株憾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情壁肋,我是刑警寧澤号胚,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站浸遗,受9級特大地震影響猫胁,放射性物質發(fā)生泄漏。R本人自食惡果不足惜跛锌,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一弃秆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧髓帽,春花似錦菠赚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至必盖,卻和暖如春拌牲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背歌粥。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工塌忽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人失驶。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓土居,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子擦耀,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,732評論 25 707
  • UML概述 UML簡介 UML (Unified Modeling Language)為面向對象軟件設計提供統(tǒng)一的...
    aron1992閱讀 512評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理棉圈,服務發(fā)現(xiàn),斷路器埂奈,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 有感于電影《夏洛特煩惱》迄损,感嘆的核心是“節(jié)奏”。(純感嘆账磺,無干貨) 看完《夏洛特煩惱》的感覺就是:語言夸張但表現(xiàn)自...
    鹽蔥蔥閱讀 349評論 0 3
  • 2017年7月2日芹敌,黨的生日剛過,美麗高唐書畫之鄉(xiāng)垮抗。來自各行各業(yè)的愛心人士組成一個大家庭的氏捞,經(jīng)常做一些送溫暖,獻愛...
    邢躍華Aa閱讀 193評論 0 0