舉例提問
你有什么方法在項目中實現(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
下包含了GaodeMap
和BaiduMap
兩個文件夾)
集成高度地圖
然后我們需要再集成高德地圖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)建兩個類BaiduMapView
和GaodeMapView
并且這兩個類都實現(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芦瘾!