适配器模式(Adapter Pattern)是一种结构型设计模式,旨在将一个类的接口转换成客户端所期待的另一种接口形式,使得原本因接口不兼容而不能一起工作的类可以一起工作。该模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。这个类被称为适配器、转换器(Converter)、包装器(Wrapper)或中介(Mediator)。
一、适配器模式的核心概念
1、目标接口(Target)
客户所期待的接口。目标可以是具体的类或抽象类,也可以是接口。
2、源接口(Adaptee)
需要适配的接口。
3、适配器(Adapter)
把源接口转换成目标接口。通常情况下,适配器类是适配器模式的核心,适配器通过继承或依赖源接口(Adaptee),并实现目标接口(Target)来达成适配的目的。
二、适配器模式的类型
适配器模式主要有两种形式:类适配器模式和对象适配器模式(也称为接口适配器模式)。
1、类适配器模式
通过多重继承对一个接口与另一个接口进行匹配,使得原本由于接口不兼容而不能一起工作的类可以一起工作。在Java等不支持多重继承的语言中,通常使用组合(即适配器持有Adaptee的引用)来实现类似的功能。
2、对象适配器模式
基于对象组合的关系,而不是继承。这种适配器模式把Adaptee的引用包装在Adapter类中,然后再通过Adapter类来实现Target接口。
三、适配器模式的应用场景
当你想使用一个已经存在的类,而它的接口不符合你的需求时。
你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)一起工作。
你想使用一个已经存在的子类,但是你不能通过继承来复用它的代码。
当你需要将一些已存在的子类迁移到新的接口时,但是你不想修改它们的类结构。
四、代码示例
下面我们通过两个具体的例子来展示类适配器模式和对象适配器模式的应用。
示例一:类适配器模式
假设我们有一个旧版的电源插座(Adaptee),它的接口不兼容新式的电器设备(Target)。我们需要一个适配器来让电器设备能够使用这个旧版的插座。
// 目标接口,新电器的接口
interface NewElectricDevice { void connectToPower();
} // 源接口,旧插座的接口
class OldPowerSocket { public void provideOldStylePower() { System.out.println("Providing power in old style..."); }
} // 类适配器类,继承OldPowerSocket并实现NewElectricDevice接口
class AdapterClass extends OldPowerSocket implements NewElectricDevice { @Override public void connectToPower() { super.provideOldStylePower(); // 调用旧接口的方法 System.out.println("Adapting old style power for new device..."); }
} // 客户端代码
public class Client { public static void main(String[] args) { NewElectricDevice device = new AdapterClass(); device.connectToPower(); // 输出:Providing power in old style... Adapting old style power for new device... }
}
示例二:对象适配器模式
假设我们仍然使用相同的旧插座和新电器设备接口,但这次我们使用对象适配器模式。
java
复制代码
// 目标接口,新电器的接口
interface NewElectricDevice { void connectToPower();
} // 源接口,旧插座的接口
class OldPowerSocket { public void provideOldStylePower() { System.out.println("Providing power in old style..."); }
} // 对象适配器类,持有OldPowerSocket的引用并实现NewElectricDevice接口
class AdapterObject implements NewElectricDevice { private OldPowerSocket oldSocket; public AdapterObject(OldPowerSocket oldSocket) { this.oldSocket = oldSocket; } @Override public void connectToPower() { oldSocket.provideOldStylePower(); // 调用旧接口的方法 System.out.println("Adapting old style power for new device..."); }
} // 客户端代码
public class Client { public static void main(String[] args) { OldPowerSocket oldSocket = new OldPowerSocket(); NewElectricDevice device = new AdapterObject(oldSocket); device.connectToPower(); // 输出:Providing power in old style... Adapting old style power for new device... }
}
五、适配器模式的优缺点
1、优点
更好的复用性:
如果有一个类,它与一些现有的类接口不兼容,那么适配器模式允许我们重用这些现有的类而不需要修改它们的代码。
更好的扩展性:
在系统设计时,如果我们需要添加一些新的接口,而新的接口与旧的接口不兼容,使用适配器模式可以使我们不需要修改现有的代码,只需要添加一个新的适配器类即可。
灵活性:
适配器模式使我们可以灵活地插入接口,如果我们需要修改一个接口,而该接口已经被多个类实现,那么我们可以使用适配器模式来创建一个新的接口,同时让旧的接口实现这个新的接口。
2、缺点
过多的使用适配器,会让系统非常零乱:
由于使用适配器模式需要引入许多适配器类,这些适配器类只是简单地实现了接口,并没有其他的业务逻辑,这会让系统的类数量变得很多,不便于管理。
代码可读性变差:
如果系统中使用了太多的适配器,可能会让其他开发者难以理解系统的真正意图,特别是对于一些不熟悉适配器模式的开发者来说,他们可能会感觉这些类非常难以理解。
六、总结
适配器模式是一种非常有用的设计模式,它允许我们将不兼容的接口进行适配,使得原本不能一起工作的类可以一起工作。在软件开发中,我们经常会遇到接口不兼容的问题,使用适配器模式可以很好地解决这些问题。然而,我们也需要注意到适配器模式的缺点,避免过度使用导致系统变得复杂和难以理解。