结构型模式之:
适配器模式- 桥接模式
- 组合模式
- 装饰模式
- 外观模式
- 代理模式
- 享元模式
1. 什么是适配器模式?
举个例子,假设有一个英国插座,而你的电器插头是美国标准的,这两种标准不兼容。在这种情况下,你可以使用一个插座适配器来解决问题。适配器将英国插座的接口转换为美国插座的接口,这样你的电器就可以在英国的插座上使用了。
适配器模式,主要是依赖继承或者组合的方法,继承是套一层的方法,组合是对象注入的方法,通过不同的方法调用不同的已有的对象的方法。通过继承的适配器模式叫类适配器模式,通过注入对象的适配器模式叫做对象适配器。
// 定义美国插座接口
interface USPlug {
void plugIn();
}
// 美国插座实现类
class USPlugImpl implements USPlug {
@Override
public void plugIn() {
System.out.println("Plugging into US plug...");
}
}
// 定义中国插座接口
interface ChinaPlug {
void plugIn();
}
// 中国插座实现类
class ChinaPlugImpl implements ChinaPlug {
@Override
public void plugIn() {
System.out.println("Plugging into China plug...");
}
}
// 定义适配器接口
interface Adapter {
void plugIn();
}
// 美国插座适配器,将美国插座适配到中国插座
class USPlugAdapter implements Adapter {
private USPlug usPlug;
public USPlugAdapter(USPlug usPlug) {
this.usPlug = usPlug;
}
@Override
public void plugIn() {
usPlug.plugIn();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 使用美国插座
USPlug usPlug = new USPlugImpl();
// 使用美国插座适配器将美国插座适配到中国插座
Adapter adapter = new USPlugAdapter(usPlug);
// 插入中国插座
adapter.plugIn();
}
}
在这个例子中,美国插座和中国插座是两个不兼容的接口。我们通过对象适配器模式,定义了一个适配器接口 Adapter,并创建了一个美国插座适配器 USPlugAdapter,它实现了适配器接口,并通过组合的方式持有美国插座对象。当客户端需要使用中国插座时,我们可以通过适配器来将美国插座适配到中国插座,使得美国插座能够在中国插座上使用。
适配器的实现方法还有另外一种,那就是类适配器,对象适配主要是通过组合的方式实现,类适配器主要是通过继承的方式实现。接下来我们将上面的方法改成类适配器。
// 定义适配器接口
interface Adapter {
void plugIn();
}
// 美国插座实现类
class USPlug {
public void plugIn() {
System.out.println("Plugging into US plug...");
}
}
// 中国插座接口
interface ChinaPlug {
void plugIn();
}
// 中国插座实现类
class ChinaPlugImpl implements ChinaPlug {
public void plugIn() {
System.out.println("Plugging into China plug...");
}
}
// 美国插座适配器,将美国插座适配到中国插座
class USPlugAdapter extends USPlug implements Adapter {
@Override
public void plugIn() {
super.plugIn();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 使用适配器,将美国插座适配到中国插座
Adapter adapter = new USPlugAdapter();
// 插入中国插座
adapter.plugIn();
}
}
在类适配器方式中,我们将适配器类 USPlugAdapter 继承了美国插座类 USPlug,并实现了适配器接口 Adapter。通过继承,适配器类既拥有了美国插座的功能,又实现了适配器接口,从而可以在客户端中被用作适配器。
2.适配器的使用场景
-
接口不兼容 适配器模式允许你创建一个中间层类, 其可作为代码与遗留类、 第三方类或提供怪异接口的类之间的转换器。
-
重用旧组件 如果您需要复用这样一些类, 他们处于同一个继承体系, 并且他们又有了额外的一些共同的方法, 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性 。
-
系统扩展- 兼容老版本接口
你可以扩展每个子类, 将缺少的功能添加到新的子类中。 但是, 你必须在所有新子类中重复添加这些代码, 这样会使得代码冗余。
将缺失功能添加到一个适配器类中是一种优雅得多的解决方案。 然后你可以将缺少功能的对象封装在适配器中, 从而动态地获取所需功能。 如要这一点正常运作, 目标类必须要有通用接口, 适配器的成员变量应当遵循该通用接口。 这种方式同装饰器模式非常相似。
3.适配器模式的缺点
- 增加系统复杂性: 引入了适配器类,增加了代码的复杂性和理解难度。
- 可能导致过多的适配器类: 如果系统中需要适配的类很多,可能会导致需要编写大量的适配器类,增加了维护的工作量。
- 不符合开闭原则: 当需要适配新的类时,可能需要修改现有的适配器类,违反了开闭原则。
- 可能引入性能损耗: 在进行对象适配时,可能需要进行类型转换等操作,可能会带来一定的性能损耗。