✨模式类型✨✨ | ✨✨难度✨ ✨ | ✨✨实用性✨✨ | ✨✨重要程度✨✨ | ✨✨经典性✨✨ | ✨✨历史性✨ |
---|---|---|---|---|---|
结构型模式 | ★★★ ⬇️ | ★★★★★ ⬆️ | ★★★★★ ⬆️ | 💚 ⬆️ | 💚 ⬆️ |
适配器模式(Adapter Pattern
) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper
)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。简单来说:适配器模式允许您将其他不兼容的对象包装在适配器中,以使其与另一个类兼容。
在软件工程中,适配器模式是一种软件设计模式,它允许将现有类的接口用作另一个接口。它通常用于使现有类与其他类一起工作而无需修改其源代码。
- 在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配器模式。
- 通常情况下,客户端可以通过目标类的接口访问它所提供的服务。有时,现有的类可以满足客户类的功能需要,但是它所提供的接口不一定是客户类所期望的,这可能是因为现有类中方法名与目标类中定义的方法名不一致等原因所导致的。
- 在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(
Adapter
),它所包装的对象就是适配者(Adaptee
),即被适配的类。 - 适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。
客户需要调用一个目标接口完成业务,但当前系统中的接口能满足业务的功能,但由于接口不合适。此时,运用适配器模式将当前接口的业务进行包装,让客户端调用的接口通过包装器能够实现客户端调用业务的方法。
Target
目标抽象类:相当于drivingcar
示例中的Car
;客户端需要调用的类,通过目标类完成接口业务的调用。Adapter
适配器类:相当于drivingcar
示例中的BusAdapter
;需要实现目标Target
类或接口,让适配器具有Target
的功能方法(调用当前系统现有的方法去实现)Adaptee
适配者类:相当于drivingcar
示例中的Driver
;调用者类通过实现Target
中的方法功能,完成业务调用。Client
客户类:相当于drivingcar
示例中的App
,调用Adaptee
完成业务调用
-
优点
-
可以让任何两个没有关联的类一起运行:将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
-
增加了类的透明性和复用性:将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
-
灵活性和扩展性都非常好:通过使用配置文件(如数据库连接),可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
-
类适配器模式还具有如下优点:
- 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
-
对象适配器模式还具有如下优点:
- 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
-
-
缺点
-
过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
-
由于
JAVA
至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。 -
类适配器模式的缺点如下:
- 对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
-
对象适配器模式的缺点如下:
- 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
-
适配器模式的实现要点如下:
- 需要有目标对象Target,可以是类或者接口。目标对象是客户端需要调用的接口,来完成业务。
- 有一个现成的类或者接口,它能间接的完成Target接口的业务。
- 需要一个Adapter适配器,它需要实现目标对象Target,通过调用现有的类中的方法,完成对Target接口的方法实现。
- 需要一个Adaptee:适配者类,通过实现
Target
中的方法功能,完成业务调用。 - 最后客户端通过适配者类Adaptee获取目标对象的实现,传入Adapter适配器就能完成目标接口的业务调用。
假设一下你的存储卡里有一些照片,你需要把它们转移到你的电脑上。为了转移它们,你 需要一些与你的电脑接口兼容的适配器,这样你就可以将存储卡连接到你的电脑上。这里, 读卡器就起到了适配器的作用。更经典的例子就是人尽皆知的电源适配器了,一个三脚的 插头不能连接到两个孔的插座上,它需要一个电源适配器,使它与两个分叉的插座兼容。
适配器模式适用于:
- 系统需要使用现有的类,而此类的接口不符合系统的需要。
- 想创建一个可重用的类,它与不相关或不可预见的类合作,即不一定具有兼容接口的类。
- 你需要使用几个现有的子类,但通过对每个子类进行子类化来调整它们的接口是不切实际的。对象适配器可以调整其父类的接口。
- 大多数使用第三方库的应用程序使用适配器作为应用程序和第三方库之间的中间层,以将应用程序与库分离。如果必须使用另一个库,则只需要新库的适配器,而无需更改应用程序代码。
java.util.Arrays#asList()
javax.swing.JTable(TableModel)
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)
javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()
- 适配器模式将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。简单来说:适配器模式允许您将其他不兼容的对象包装在适配器中,以使其与另一个类兼容。
- 在软件工程中,适配器模式是一种软件设计模式,它允许将现有类的接口用作另一个接口。它通常用于使现有类与其他类一起工作而无需修改其源代码。
- 客户需要调用一个目标接口完成业务,但当前系统中的接口能满足业务的功能,但由于接口不合适。此时,运用适配器模式将当前接口的业务进行包装,让客户端调用的接口通过包装器能够实现客户端调用业务的方法。
- 适配器模式可以让任何两个没有关联的类一起运行,增加了类的透明性和复用性,灵活性和扩展性都非常好。
- 系统需要使用现有的类,而此类的接口不符合系统的需要;想创建一个可重用的类,它与不相关或不可预见的类合作,即不一定具有兼容接口的类;第三方库的应用程序使用适配器作为应用程序和第三方库之间的中间层,以将应用程序与库分离。