软件开发,需求变更是家常便饭,前期调研不仔细,app做好了,客户不满意,领导一句话,变更;客户觉得那种操作习惯好一些,变更;地图不显示不完全,换地图。
既然避免不了,我们就应该把需要变动的隔离出来,不变的放另外的地方。
以下通过一个加载Google和apple地图的例子,来试图说明如何封装需求的变更,各位看官看完后,还请大家留下你们宝贵的意见。
加载苹果地图很方便,官方都有文档,主要是MapKit框架,这个就不多说了,好,我们把代码集成到工程里面去:
CGRect rect=[UIScreen mainScreen].bounds; _mapView=[[MKMapView alloc]initWithFrame:rect]; [self.view addSubview:_mapView]; //设置代理 _mapView.delegate=self; //请求定位服务 _locationManager=[[CLLocationManager alloc]init]; if(![CLLocationManager locationServicesEnabled]||[CLLocationManager authorizationStatus]!=kCLAuthorizationStatusAuthorizedWhenInUse){ [_locationManager requestWhenInUseAuthorization]; } //用户位置追踪(用户位置追踪用于标记用户当前位置,此时会调用定位服务) _mapView.userTrackingMode=MKUserTrackingModeFollow; //设置地图类型 _mapView.mapType=MKMapTypeStandard; //添加大头针 [self addAnnotation];
一切都很完美,可是突然领导对我们说,苹果地图不好用,我们要用Google的,好,我们把上面的代码注释掉,然后到Google的官网上查api,然后再集成。
好吧,Google地图和苹果地图完全不一样,代码重新写,结构变了:
GoogleMapEntry *entry = [[GoogleMapEntry alloc] init];
if (object!=nil && [object isKindOfClass:[NSDictionary class]]) {
[GMSServices provideAPIKey:@"AIzaSyCX4TM8eqps-FUKHY3bz1vVQK1PDzn_bGU"];
}
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:6];
[entry setMapView:[GMSMapView mapWithFrame:CGRectZero camera:camera]];
((GMSMapView *)entry.mapView).myLocationEnabled =YES;
。。。。。
然后改调用的地方,全文搜索,改了一两天,终于改好了,问题又来了,由于代码不兼容,运行的时候老是报方法找不到。。
然后,过一段时间,领导说,你还是改成百度地图吧,Google地图在中国不好用。。
我们有更好的方法吗?
我们通过对比苹果地图和Google地图,发现其实要显示一个地图呀,两个api有类似的方法,初始化地图并显示和添加大头针,
于是,我们提出这两个方法,写到基类里面:
#import <Foundation/Foundation.h>
@interface SuperMapThird : NSObject
@property (nonatomic,retain) id mapView;
+(id)InitMapThirdUserInfo:(id)object;
/**
* 添加大头针
*
* @param userInfo key: Latitude, Longitude
*/
-(void)addAnnotationView:(id)userInfo;
@end
苹果地图继承这两个基类:
#import "SuperMapThird.h"
@interface AppleMapEntry : SuperMapThird
@end
#import "AppleMapEntry.h"
#import <MapKit/MapKit.h>
#import "MKMapView+MapViewUtil.h"
@implementation AppleMapEntry
+(id)InitMapThirdUserInfo:(id)object {
AppleMapEntry *entry = [[AppleMapEntry alloc] init];
[entry setMapView:[[MKMapView alloc] initWithFrame:CGRectMake(10,110, 300,DEV_MAIN_SCREEN-110-50-40-64)]];
MKMapView *mapView = entry.mapView;
。。。。
return entry;
}
-(void)addAnnotationView:(id)userInfo {
if (userInfo!=nil && [userInfo isKindOfClass:[NSDictionary class]]) {
CLLocationDegrees latitude = [[userInfo objectForKey:@"Latitude"] doubleValue];
CLLocationDegrees longitude = [[userInfo objectForKey:@"Longitude"] doubleValue];
MKMapView *mapView = (MKMapView *)self.mapView;
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude;
coordinate.longitude = longitude;
MKPointAnnotation *ann = [[MKPointAnnotation alloc] init];
ann.coordinate = coordinate;
//[ann setTitle:stDetail.StoreName];
//[ann setTitle:@"购物好去处"];
//触发viewForAnnotation
[mapView addAnnotation:ann];
}
}
@end
谷歌地图也继承这个类:
#import <Foundation/Foundation.h>
#import <GoogleMaps/GoogleMaps.h>
#import "SuperMapThird.h"
@interface GoogleMapEntry : SuperMapThird
@end
#import "GoogleMapEntry.h"
@implementation GoogleMapEntry
+(id)InitMapThirdUserInfo:(id)object {
GoogleMapEntry *entry = [[GoogleMapEntry alloc] init];
。。。
return entry;
}
-(void)addAnnotationView:(id)userInfo {
if (userInfo!=nil && [userInfo isKindOfClass:[NSDictionary class]]) {
CLLocationDegrees latitude = [[userInfo objectForKey:@"Latitude"] doubleValue];
CLLocationDegrees longitude = [[userInfo objectForKey:@"Longitude"] doubleValue];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude longitude:longitude zoom:6];
GMSMapView *gsmMap = self.mapView;
gsmMap = [GMSMapView mapWithFrame:CGRectZero camera:camera];
gsmMap.myLocationEnabled = YES;
//create a marker in the center of the map
GMSMarker *marker = [[GMSMarker alloc]init];
marker.position = CLLocationCoordinate2DMake(-33.86,151.20); //地图显示的大头针做坐标
marker.title = @"Sydney";
marker.snippet = @"Australia";
marker.map = self.mapView;
}
}
@end
#import <Foundation/Foundation.h>
#import "SuperMapThird.h"
@interface MapThirdFactory : NSObject
+(SuperMapThird *)getMapEntry:(NSInteger)type userInf:(id)object;
@end
#import "MapThirdFactory.h"
#import "MapThirdDefine.h"
#import "AppleMapEntry.h"
#import "GoogleMapEntry.h"
@implementation MapThirdFactory
+(SuperMapThird *)getMapEntry:(NSInteger)type userInf:(id)object {
SuperMapThird *entry = nil;
switch (type) {
//苹果地图
case MAPTHIRDAPPLE:
entry = [AppleMapEntry InitMapThirdUserInfo:object];
break;
default:
//默认返回谷歌地图
entry = [GoogleMapEntry InitMapThirdUserInfo:object];
break;
}
return entry;
}
@end
如此,现在app调用只跟工厂类有关了
MapThirdManage *manage = [[MapThirdManage alloc] init];
[manage setMapThirdEntry:[MapThirdFactory getMapEntry:type userInf:object]];
如果领导说我想还是用百度地图吧,好吧,我们重新写一个类,继承SuperMapThird,然后实现他的两个方法,
最后在app的调用里面把type改成所定义的百度地图的类型,由于初始化地图和添加大头针都是基类的方法,
跟子类实现无关,所以我们不需要全文搜索了,嘿嘿。。。