定义
使一个类和接口不匹配的其他类进行交互。 适配器可帮助两个不兼容的接口一起工作。 接口可能不兼容,但内部功能应适合需要。 适配器设计模式允许不兼容的类通过转换来一起工作
将一类的接口转换为客户端期望的接口。
意图
- 将一个类的接口转换为client类期望的另一个接口
- 适配器让类可以协同工作,否则会因为接口不兼容无法进行。
种类
- 类适配器 通过继承实现:从不兼容的类派生出新类并且添加我们需要的方法使得派生类满足预期接口。
- 对象适配器 通过对象组合实现:新类中包含原始类并且在新类里创建方法以实现调用的转换。
参与者
- Target : 定义client使用的特定于某个域的接口。
- Adapter: 将Adaptee接口适配到Target接口。
- Adaptee: 定义需被适配的已有接口
- Client : 与遵循Target接口的对象协作。
举例(source:https://github.com/iluwatar/java-design-patterns)
故事是这样的: 海盗来了! 我们需要一个划艇{RowingBoat}逃离! 我们只有一个渔船 {FishingBoat},队长。 我们没有时间在造一个新船!
我们需要重用这个渔船。 船长需要一艘可以操作的划艇。 然后使用适配器模式让船长可以使用渔船。
该例子使用对象适配器 ,也就是将渔船类通过组合的方式包含在适配器中
类图:
Client :Captain
public class Captain {
private RowingBoat rowingBoat;
public Captain() {}
public Captain(RowingBoat rowingBoat) {
this.rowingBoat = rowingBoat;
}
public void setRowingBoat(RowingBoat rowingBoat) {
this.rowingBoat = rowingBoat;
}
public void row() {
rowingBoat.row();
}
}
Adaptee:FishingBoat
public class FishingBoat {
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
public void sail() {
LOGGER.info("The fishing boat is sailing");
}
}
Adapter: FishingBoatAdapter
public class FishingBoatAdapter implements RowingBoat {
private FishingBoat boat;
public FishingBoatAdapter() {
boat = new FishingBoat();
}
@Override
public void row() {
boat.sail();
}
}
Target:RowingBoat
public interface RowingBoat {
void row();
}
给这个船长一个渔船让他开走
public static void main(String[] args) {
// The captain can only operate rowing boats but with adapter he is able to use fishing boats as well
Captain captain = new Captain(new FishingBoatAdapter());
captain.row();
}
优点
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
- 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式还具有如下优点:
由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式还具有如下优点:
一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点
类适配器模式的缺点如下:
对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式的缺点如下:
与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
分享到: