适配器模式
当项目中的埋点使用了友盟的SDK,哪一天,产品要求把友盟的SDK换成神策数据的,因为两个SDK的接口不一样,如果要更换,那不是得替换掉很多代码
比如以前使用友盟的接口是[UMMob eventId:@"123"],神策是[Analyze mobEventId:@"123"],因为我们项目大量的使用了友盟了,所以这时候,我们可以新建一个类叫UMAdapter,类中的方法为eventId:,这样我们就只需要替换UMMob类
那么这种形式就是适配器模式了,UMAdapter为适配器,eventId:为目标接口,Analyze为要适配的类
看看具体的实现
新建一个类UMAdapter继承Analyze,实现一个方法eventId:,方法的实现为
- (void)eventId:(NSString *)eventId
{
[self mobEventId:eventId];
}
这样我们就可以使用UMAdapter类去替换友盟了,那么这种方式呢,就是最简单的适配器模式了
有人可能会说,适配器模式不是还得设计接口吗,iOS上叫设计协议。
我们看下适配器模式的介绍
将一个类的接口转换为客户希望的另一个接口,它使得原来由于兼容问题不能一起工作的那些类可以一起工作。
我的理解,存在一个类的接口,不满足我们使用,所以我们才使用适配器,例如刚才的神策接口,我们使用适配器,将其适配成类似友盟的接口
使用适配器还有条件,往往是适配出相似功能的才使用适配器,比如刚才的神策适配成友盟接口,功能都是埋点,不能说将神策埋点的接口,适配成shareSDK,所以说是相似功能才进行适配
适配器模式的角色有适配器,被适配者,目标接口,在刚才的例子中适配器就是UMAdapter,被适配者是Analyze(神策SDK),目标接口是eventId:,所以回到刚才的问题,为什么不需要设计接口,协议呢,这里要看对接口的理解
我的个人理解
提供给外部使用的方法,无论是协议的形式,抽象类虚函数的形式,甚至具体类的方法,只要是提供给外部使用的都可以叫接口
那么假如我要适配的接口有10个,是一系列的,那么我要去优化他,我就可以定义一个协议,把这堆方法放到这个协议中
我对协议使用场景的理解,有一个使用场景哦
协议可以放着同一系列功能的方法,这样可以提高代码的结构化和可读性,比把这堆方法直接写到具体类中,然后再写#pragma mark - 分段 好一点 常见的这种用法是定义一个协议,然后一个基类,基类里面实现协议,将协议的方法充当虚函数,经常看到这种写法,在适配器模式里面,但是我还不能很好的去理解这种操作,欢迎交流这点!!!
刚才之所以直接写到具体类中,是因为只有一个方法,没有必要去过度的设计,还有刚才一开始那样写想表达的意思是,理解一种设计模式,应该是先理解他是为了解决什么问题,怎么去解决的,然后具体代码怎么做,而不是墨守成规的去遵守,一定要设计接口,一定要用继承等等。
比如刚才的UMAdapter继承Analyze
适配器继承被适配器,这种模式叫类适配器
之所以要继承,无非就是想在方法eventId:中直接调用Analyze类的方法,这样简单的实现了转换
那么除了这种方法,我们还可以不用继承呀。在UMAdapter类中声明Analyze类,在转换接口中调用Analyze对象的mobEventId方法就可以啦,这种就是对象适配器模式
@interface UMAdapter : NSObject
@property (nonatomic, strong) Analyze *analyze;
@end
@implementation UMAdapter
- (void)eventId:(NSString *)eventId
{
[self.analyze mobEventId:eventId];
}
- (Analyze *)analyze
{
if (!_analyze)
{
_analyze = [Analyze alloc] init];
}
return _analyze;
}
@end
上面讲了适配器,被适配器,接口,类适配模式,对象适配器模式,接下来再讲最后一个,缺省适配器模式
缺省就是默认 default的意思
在java中,如果你定义了接口
public interface InterfaceA {
public void fun1();
public void fun2();
public void fun3();
public void fun4();
public void fun5();
}
那么你想要实现这个接口,就得实现里面的所有方法,不然会报错
所以有个问题,比如在java里面,适配器A只需要实现fun1(),fun2(),fun3(),就可以了,适配器B只需要实现fun3(),fun4(),fun5()就可以了
那么如果要写成适配器模式,在java里面,这种情况就得定义两套接口,分别给适配器A和B用,那么这样代码肯定会有重复,多余
那么缺省适配器模式就来了
定义一个抽象适配器类,实现接口InterfaceA,在里面实现接口InterfaceA的所有方法,并且给予默认实现,那么适配器A,适配器B就可以继承抽象适配器类,分别去重写想要的接口就可以了
这种就是缺省适配器模式
那么在iOS,接口一般是协议来搞,协议有可选和必选两种,那么就没有这种问题
适配器的应用场景
被动使用:就是本文的例子了
主动使用:比如目前项目基于AFNetWorking设计网络层的,但是我设计之初就想好,以后可能需要更换网络请求框架,那么如果真的要更换了,那不是AFNetWording很多接口都得换,那么不就需要使用适配器模式了,但是被动使用还不如主动出击,就是设计的时候就考虑好,以后可以随意的切换不同的网络框架,推荐猿题库的一个框架YTKNetwork,这个主要设计就是考虑了这一点
总结
适配器模式角色,适配器,被适配器,源接口(要转换的接口),目标接口(外部想要的接口)
适配器有类适配器,对象适配器,缺省适配器,其实本质上都是大同小异,比如类适配器和对象适配器,只是适配器->被适配器之间的关系不同而已,最后的目的都是在适配器中调到源接口
缺省适配器 就刚才的例子中,是java中实现接口必须全部实现,所以才有这个由来,iOS就没有这个问题













网友评论