iOS-面向协议编程

作者: 骑毛驴的小强 | 来源:发表于2017-01-11 23:41 被阅读297次

    用工厂方法时,先定义了一个基类,在基类的声明中定义了一系列的方法,类实现里面并不需要实现,而是在子类里面实现的,需要的只是基类中的.h文件的方法声明。这个是不是和协议有点像,定义一个基协议,让各个工厂类都遵守这个基协议。我们就拿地图说事。百度地图和高德地图的视图都是继承的UIView,请看代码。
    1>首先我们先定义2个基协议。

    #import <UIKit/UIKit.h>
    #import "ImapView.h"
    
    @protocol IMapFactory <NSObject>
    
    - (id<ImapView>)getMapViewWithFrame:(CGRect)frame;
    
    @end
    
    #import <UIKit/UIKit.h>
    
    @protocol ImapView <NSObject>
    
    - (instancetype)initWithFrame:(CGRect)frame;
    
    - (UIView *)getMapView;
    
    @end
    

    第一个协议是用来生产一个遵守IMapFactory这个协议的工厂。第二个协议就是通过遵守IMapFactory协议的工厂来生产地图。

    给每个第三方地图定义2个类,一个类是来生产地图工厂,另一个就是通过工厂来生产地图视图。

    .h文件
    #import <UIKit/UIKit.h>
    
    #import "IMapFactory.h"
    
    @interface BaiduMapFactory : NSObject <IMapFactory>
    
    @end
    

    遵守了IMapFactory就能拿到协议里面的方法,从而可以返回一个遵守ImapView协议的地图视图。同样初始化方法也可以写在地图工厂里,从而做到瘦身程序入口方法

    .m文件
    #import "BaiduMapFactory.h"
    #import "BaiduMapView.h"
    #import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
    #import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
    
    @interface BaiduMapFactory ()
    @property (nonatomic,strong) BMKMapManager *mapManager;
    @end
    
    @implementation BaiduMapFactory
    
    - (instancetype)init {
    
        if (self = [super init]) {
            _mapManager = [[BMKMapManager alloc] init];
            [_mapManager start:@"HBnGpGicUfd6SwSr5oCMre3asI29U0GG" generalDelegate:nil];
        }
        return self;
    }
    
    - (id<ImapView>)getMapViewWithFrame:(CGRect)frame {
        return [[BaiduMapView alloc] initWithFrame:frame];
    }
    
    @end
    

    让地图视图这个类遵守ImapView这份协议。用来返回地图视图。

    .h文件
    #import <UIKit/UIKit.h>
    #import "ImapView.h"
    
    @interface BaiduMapView : UIView <ImapView>
    
    @end
    
    .m文件
    #import "BaiduMapView.h"
    #import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
    #import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
    
    @interface BaiduMapView ()
    @property (nonatomic,strong) BMKMapView *mapView;
    @end
    
    @implementation BaiduMapView
    
    - (instancetype)initWithFrame:(CGRect)frame {
    
        if (self = [super initWithFrame:frame]) {
            _mapView = [[BMKMapView alloc] initWithFrame:frame];
        }
        return self;
    }
    
    - (UIView *)getMapView {
    
        return _mapView;
    }
    @end
    

    等等,这个工厂谁来创建了,难道要在客户端去手动实例化工厂吗?no no no 这种设计原则太烂了。定义一个地图引擎用来返回工厂,而返回的工厂遵守IMapFactory协议就行。

    .h文件
    #import <Foundation/Foundation.h>
    #import "IMapFactory.h"
    
    typedef NS_ENUM(NSInteger, mapType) {
        baidu,
        gaode
    };
    
    @interface MapEngine : NSObject
    
    - (id <IMapFactory>)getMapFactoryWithType:(mapType)type;
    @end
    
    .m文件
    #import "MapEngine.h"
    #import "BaiduMapFactory.h"
    #import "GaodeMapFactory.h"
    
    @implementation MapEngine
    
    - (id <IMapFactory>)getMapFactoryWithType:(mapType)type {
        
        if (type == baidu) {
            return [[BaiduMapFactory alloc] init];
        } else {
        
            return [[GaodeMapFactory alloc] init];
        }
    }
    @end
    

    那么客户端的代码就简单了,引擎->工厂->地图。

    MapEngine *engine = [[MapEngine alloc] init];
    id <IMapFactory> factory = [engine getMapFactoryWithType:baidu];
    id <ImapView> mapView = [factory getMapViewWithFrame:self.view.frame];
    [self.view addSubview:[mapView getMapView]];
    

    高德地图也是一样,定义2个类,一个工厂,一个视图。分别遵守2个协议。切换地图时,只需要修改一个参数即可替换。
    总结:面向协议就是充分利用了只要继承了协议,就能获取协议中所有的方法这个特点,和工厂方法有点类似。

    相关文章

      网友评论

        本文标题:iOS-面向协议编程

        本文链接:https://www.haomeiwen.com/subject/wnurbttx.html