买过港版iPhone的人都知道,港版iPhone的充电器使用的是英标,与内地的国标标准不通用。因此,如果想在内地使用港版的充电器,就必须再买个转接头,使港版充电器的插头能够与国标插口“适配”。这个转接头的功能即类似于我们这里提到的“适配器”。
在软件设计中,已有的类与新接口之间不兼容的问题相当常见,同时,我们又不想为新的接口而重写现有的类。此时,就需要用到“适配器模式”。
定义:将一个类的接口转换为客户希望的另一个接口,它使得原来由于兼容问题不能一起工作的那些类可以一起工作。(《设计模式》,Addison Wesley,1994)。
通常,适配器模式有两种实现方式:类适配器,对象适配器。
1、类适配器
类适配器主要通过继承来适配两个接口,在Objective-C中,多重继承可以通过实现协议,同时又继承基类来实现。要在OC中实现类适配器,首先要有客户端要使用的一套行为的协议,然后要用具体的适配器类来实现该协议,同时适配器类也要继承被适配者。如下图所示。
Adapter是一个Target(目标接口)类型,同时也是一个Adaptee(被适配的类)类型。Adapter重载Target的request方法,但没有重载Adaptee的specificRequest方法,而是在其request方法中调用父类的specificRequest方法(即:[super specificRequest])。当request方法在运行时,向Adaptee发送super消息时,Adaptee按自己的方式执行specificRequest方法。注意:只有当Target是协议而不是类时,类适配器才能用Objective-C实现。
由于类适配器模式采用多继承方式实现,在一定程度上增加了程序的耦合性,而且OC语言本身并不支持多重继承,只能通过实现协议并继承父类来实现。因此,在OC中较常用的还是下一种:对象适配器模式。
2、对象适配器
与类适配器不同的是,对象适配器不继承被适配的类,而是组合了一个对被适配的类的引用,如图所示。
Target和Adapter之间的关系与类适配器相同,而Adapter和Adaptee之间的关系从“属于(继承)”变成了“包含(组合引用)”。这种情况下Adapter持有一个对Adaptee的引用,在request方法中,Adapter发送[adaptee specificRequest]消息,以间接方法Adaptee的specificRequest方法,然后实现客户端请求的其他部分。
示例代码如下:
Target:
[objc]view plaincopy
@protocolTargetDelegate
@optional
-(void)request;
@end
@interfaceTarget
@property(weak,nonatomic)iddelegate;
@end
@implementation
...
// 通知代理,调用相应的方法
if(_delegate && [_delegaterespondsToSelector:@selector(request)]) {
[_delegaterequest];
}
...
@end
Adapter:
[objc]view plaincopy
@interfaceAdapter
{
Target*_target;
Adaptee*_adaptee;
}
@end
@implementationAdapter()
...
// 设置代理
_target.delegate=self;
// 实现代理方法
-(void)request
{
[_adapteespecificRequest];
}
...
@end
显然,iOS中的委托(Delegate)属于对象适配器。
3、使用适配器模式的情形
①、现有类的接口与需求不匹配;
②、想要复用一个类,该类能够同其他可能带有不兼容接口的类协作;
③、需要适配一个类的几个不同子类,可是让每个子类去子类化一个类适配器又不现实,此时可以使用对象适配器(委托)来适配其父类接口
网友评论