适配器模式(结构)
简介
适配器模式是一种结构型设计模式,它允许将不兼容的对象转换成可兼容的接口。主要目的是解决在不改变现有代码的情况下,使不兼容的接口之间能够正常工作,通过创建一个中间转换的适配器来将一个对象转换成我们所需要的接口。
适配器模式让原本两个不兼容的类能够兼容,并且从用户的角度看不到具体的转换,用户只是调用适配器完成转换,在用户看来,直接和目标接口交互就可以了。
模式结构
目标接口(target):需要适配的标准接口。
源对象(source):需要被适配的不兼容对象。
适配器对象(adapter):充当中间转换角色,该对象将源对象转换成目标接口。
优缺点
优点
安全可靠:封装了旧接口,对客户端透明,客户端代码无需修改。
提高复用性:可以复用不兼容的类;可以对不同的类无需修改,就可以进行组合。
扩展性好:在应用程序开发过程中,可以增加新的适配器和被适配对象。
缺点
过多的适配器会导致系统结构复杂。
如果适配器没有实现好,可能会拖慢整个系统的性能。
滥用适配器模式会导致系统设计紊乱。
应用场景
生活场景
电压转换器:不同国家的电压规格各异,同样功率的电器在不同的地方工作时需要不同的电压,电压转换器作为适配器,将不同电压转换成电器使用标准电压。
耳机转接头:有些手机没有耳机插口,需要使用转接头适配器,将耳机转换为手机支持的接口,实现对不同的耳机兼容。
程序场景
JDBC驱动程序:不同的数据库提供商实现了不同的JDBC驱动接口,使用适配器模式可以将这些不同的接口适配为标准的JDBC接口,提高应用程序的可移植性。
日志框架:Java中有多个常用的日志框架,如Log4j、SLF4J等,不同的日志框架提供的API不同,使用适配器模式可以将这些不同的API适配为一个统一的接口,方便再程序中进行日志记录和管理。
第三方库或SDK:在使用第三方库或 SDK 时,可能由于它们实现的 API 不同而导致应用程序复杂,使用适配器模式可以将不同的 API 适配为统一的接口,简化应用程序的调用。
类适配器模式
类适配器模式通过继承适配者接口,实现目标接口,实现了在适配器类中获取了两个接口与中的方法,从而实现方法对象的转换,但是由于java的单继承机制,这就要求目标必须是接口,具有一定的局限性。
耦合性高
灵活性低
实现简单
实现代码如下:
//目标接口
interface Target{
void request(); //三孔插座
}
//适配者接口
class Adaptee{
public void specificRequest(){
System.out.println("插头插入了两孔插座"); //需要一个两孔插座
}
}
//适配器类
class ClassAdapter extends Adaptee implements Target{
@Override
public void request() {
specificRequest(); //将三孔插座转换为两孔
}
}
//客户端 测试类
public class AdapterTest {
public static void main(String[] args) {
Target target=new ClassAdapter();
target.request(); //用户使用了三孔的插座,但是插入的是两孔
}
}
对象适配器模式
对象适配模式中的适配器类不再继承适配者的类,而是通过组合的方式在适配器类中获取适配者对象,从而实现将适配者转换为目标类。对比来说,比类适配器更加灵活。
耦合性低
灵活性高
实现较复杂
//适配器类
class ClassAdapter implements Target{
private Adaptee adaptee;
public ClassAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest(); //将三孔插座转换为两孔
}
}
//客户端 测试类
public class AdapterTest {
public static void main(String[] args) {
Target target=new ClassAdapter(new Adaptee());
target.request(); //用户使用了三孔的插座,但是插入的是两孔
}
}
接口适配器模式
接口适配器模式借助中间抽象类空实现目标接口中的所有方法,子类选择性重写,可以减少不必要的方法。 从表面上看,就好像是不再是客户端使用适配器,而是适配者自己去使用适配器为客户端提供我们需要的用途。
实现代码:
//目标接口
interface Target{
void request(); //三孔插座
}
//适配者接口
class Adaptee extends ClassAdapter{
@Override
public void request(){
System.out.println("插头插入了两孔插座"); //需要一个两孔插座
}
}
//适配器类
/**
* 抽象类:提供缺省实现
*/
class ClassAdapter implements Target{
@Override
public void request() {
}
}
//客户端 测试类
public class AdapterTest {
public static void main(String[] args) {
Adaptee adaptee=new Adaptee();
adaptee.request(); //用户使用了三孔的插座,但是插入的是两孔
}
}
- 感谢你赐予我前进的力量