表述 (结构型模式)
将一个类的接口转化成客户端希望的另外一个接口。适配者模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
适配器模式的实现方式
- 类适配器模式 :主要是通过继承来适配两个接口。主要是使用多重继承的方式,但是OC不支持多继承,只支持单继承,所以在iOS中我们使用继承和协议的方式来实现类的适配
- 对象适配器模式 :组合一个被适配类的引用,不是采用继承被适配的类的方式
适配器模式类图
- 类适配器模式
类适配器模式
TargetProtocol:目标协议 Adaptee:被适配对象 Adapter:适配器,实现了 request方法,但是没有去重写Adaptee类中 specificRequest方法,而是在Adapter 中的request方法中调用超类的specificRequest方法
- 对象适配器模式
对象适配器模式
TargetProtocol:目标协议 Adaptee:被适配对象 Adapter:适配器,Adapter 引用 Adaptee,在request方法中,adaptee对象调用specificRequest方法
类适配器模式与对象适配器模式对比
类适配器模式 | 对象适配器模式 |
---|---|
只针对单一具体的Adaptee类,把Adaptee适配到TargetProtocol | 可以适配多个Adaptee及其子类 |
易于重写Adaptee的方法,因为是直接通过子类化进行的适配 | 难以重载Adaptee的行为,需要借助于子类的对象而不是Adaptee本身 |
只有一个Adapter对象,无需额外的指针间接访问Adaptee | 需要额外的指针以间接访问Adaptee并适配其行为 |
使用场景
- 复用一些现存的类,但是接口又与复用环境要求不一致的情况
- 俩个类所做的事情相同或相似,但是具有不同的接口时要使用它
示例
需求:原有获取美元的类,现需要获取人民币
- 类适配器模式(通过继承来适配两个接口)
//要被适配的美元类
class AdapteeUSD {
func getUSD() -> Float {
return 100
}
}
//准备目标协议
protocol TargetCNYProtocol {
func getCNY() -> Float
}
//创建一个适配器AdapterCNY,继承自被适配的对象AdapteeUSD,并实现其目标协议
class AdapterCNY : AdapteeUSD,TargetCNYProtocol {
func getCNY() -> Float {
let usd = self.getUSD()
return usd * 6.61
}
}
//客户端调用
let adapterCNY = AdapterCNY.init()
let res = adapterCNY.getCNY()
print(res)
- 对象适配器(不继承被适配者, 他们是一个关联关系, 相当于引用了这个类)
//创建被适配的类AdapteeUSD
class AdapteeUSD {
func getUSD() -> Float {
return 100
}
}
//目标接口
protocol TargetCNYProtocol {
func getCNY() -> Float
}
//适配器
class AdapterCNY : TargetCNYProtocol {
var adaptee : AdapteeUSD
init(adaptee : AdapteeUSD) {
self.adaptee = adaptee
}
func getCNY() -> Float {
return self.adaptee.getUSD() * 6.61
}
}
//客户端调用
let USD = AdapteeUSD()
let adapterCNY = AdapterCNY.init(adaptee: USD)
let res = adapterCNY.getCNY()
print(res)