看图识模式
简单的概述适配器模式就是: 需要的东西在你面前,而短时间又无法改造它,于是我们就想办法适配它。
比如,现在一个没有电的手机和一个110V50HZ的插座在你面前,你显然要给手机充电,但是手机只需要5V-1A的输入。这时候怎么办?
打电话给电厂,把电压给我降下来
找手机厂商,把我的手机改为220V的输入
找个电源适配器
结果很显然~
模式定义
适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
适配器用于连接两种不同种类的对象,使其毫无问题的协同工作。思想很简单,适配器实现客户端所要的某种接口的行为。同时,它又连接到另一个具有(完全)不同接口与行为的对象。一边是客户端懂得如何使用的目标接口,另一边是客户端一无所知的被适配者,适配器处于两者之间。适配器的主要作用是把被适配者的行为传递给管道另一端的客户端。
何时使用适配器模式
已有类的接口与需求不符
想要一个可复用的类,该类能够同可能带有不兼容接口的其他类协作。
需要适配一个类的几个不同子类,可是每一个子类去子类化一个类适配器又不现实。那么可以使用对象适配器(也就是代理)来适配其父类的接口。
解耦(适配器里做的事情,就是一个耦合的过程)
模式结构
适配器结构图
类适配器与对象适配器的对比
类适配器与对象适配器是实现适配器模式的不同方式,但是达成了同样的目的。
类适配器 | 对象适配器 |
---|---|
只针对单一的具体Adaptee类,把Adaptee适配到Target | 可以适配多个Adaptee及其子类 |
易于重载Adaptee的行为,因为是通过直接的子类化进行的适配 | 难以重载Adaptee的行为,需要借助于子类的对象而不是Adaptee本身 |
只有一个Adapter对象,无需额外的指针间接访问Adaptee | 需要额外的指针以间接访问Adaptee并适配其行为 |
代码示例
Target(这是客户所期望的接口。目标可以是具体的或则抽象的类
,也可以是接口
)
class Target
{
public virtual void Request()
{
Console.WriteLine("普通请求");
}
}
Adaptee(需要适配的类)代码如下:
class Adaptee
{
public void SepecificRequest()
{
Console.WriteLine("特殊请求");
}
}
Adapter(通过在内部包装一个Adaptee对象,把源接口转换成目标接口),代码如下:
class Adapter : Target
{
private Adaptee adaptee = new Adaptee();
public override void Request()
{
adaptee.SepecifiRequest();
}
}
客户端端代码如下:
static void Main(String[] args)
{
Target target = new Adapter();
target.Request();
Console.Read();
}
Cocoa中更复杂的应用
以UITableView的使用为例:想要把UITableView的接口变换成客户端需要的接口。
这里的客户端是什么呢?其实就是UITableView。
那么此处什么是Target(目标接口)呢?是一个UITableViewDelegate和UITableViewDataSource。
实现协议的具体类(UIViewController)会是个适配器。那什么是与框架不匹配而需要适配的类呢——应用程序(UIViewController)中的其他类。
我们之所以说委托机制主要是适配器模式,是因为委托机制可以实现某些其他设计模式的意图,比如装饰模式。委托模式的实现有时会跟其他设计模式混在一起。
总结
适配器模式的有点很多,如:
将客户端与适配者解耦、使客户端调用更加简明(只需要调用定义的接口方法)。
但同样也有缺点
在写适配器的时候为适应目标接口,可能会有比较复杂实现过程;
无端端多出许多的类,使结构又复杂了一些。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。