Java23种设计模式之适配器模式的学习
源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns
这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23种设计的模式的各种实现方式以及应用场景,非常适用于学习以及提高我们的设计思维,如果对大家有所帮助,请记得star一下给予作者一定的精神支持,你的star是我写出更好的博客的动力,谢谢大家。
适配器模式(adapter)
什么是适配器模式?
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
适配器模式主要分为三类:类适配器模式、对象适配器模式、接口适配器模式(本文不介绍)。适配器模式属于结构型设计模式。
适配器模式中的角色
- 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
- 需要适配的类(Adaptee):需要适配的类或适配者类。
- 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
举个例子:USB网线转换器
-
当我们电脑要上网,首先得要连接上网线才行,但是电脑的接口是USB接口,而不是网线的接口,USB接口不能直接连接上网线的接口,这个时候我们就需要一个转换器帮助我们把电脑的接口转换成网线接口去连接网线,我们电脑和网线都连接上这个转换器,由这个转换器帮助我们完成电脑和网线的连接。
-
以上的电脑就相当于目标接口(Target),网线就相当于被适配器类(Adaptee),而转换器就相当于适配器(Adapter)。
-
还有一个常用的例子就是我们的手机充电,家用电是220V的,我们手机是5V的,因此我们需要使用手机充电器进行将220V降为5V给手机充电,220V就是Adaptee、手机充电器就是Adapter、5V的电就是Target。
-
而这种将一个类的接口转换成客户希望的另外一个接口的东西就被称为适配器,也就是上面例子中的转换器。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作!
下面我们使用电脑连接网线的例子作为代码实现:
实现方式一:类适配器
被适配的类:网线
/**
* 要被适配的类 这里指例子中的网线
*/
public class Adaptee {
public void request(){
System.out.println("连接网线上网!");
}
}
适配器的接口:
/**
* 接口转换器的抽象实现----USB接口转网线接口
*/
public interface NetToUsb {
public void handleRequest();
}
适配器的具体实现:转换器
/** 1.继承、类适配器
* 真正的适配器
* 需要提供USB转网线接口的功能,让电脑能够上网
*/
public class Adapter extends Adaptee implements NetToUsb {
//以上使用继承的方式可以拥有网线上网的功能
@Override
public void handleRequest() {
super.request();//拥有网线的上网功能,相当于转换连接了
}
}
目标接口:客户端(电脑)
/**
* 客户端类:想要上网,需要连接网线,但是只有USB接口,没有网线接口
*/
public class Computer {
//电脑需要连接上转换器才能上网
public void net(NetToUsb adapter){
//上网的具体实现,转到一个转接头帮我们处理上网请求
adapter.handleRequest();
}
public static void main(String[] args) {
//想要上网,需要电脑、网线、适配器
Computer computer = new Computer();//电脑
Adaptee adaptee = new Adaptee();//网线
Adapter adapter = new Adapter();//转换器
computer.net(adapter);
}
}
输出:
由于Java是单继承的,使用继承的方式会有局限性,因此有了第二种组合的方式,也叫对象适配器。
实现方式二:对象适配器(常用)
使用对象适配器的基本思路和类适配器差不多,只需要将适配器Adapter类做一些修改,将继承改为持有,这样就可以解决单继承的兼容性问题。
适配器的具体实现Adapter类:
/** 2.组合(对象适配器)---常用
* 真正的适配器
* 需要提供USB转网线接口的功能,让电脑能够上网
*/
public class Adapter2 implements NetToUsb {
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
//以上使用继承的方式可以拥有网线上网的功能
@Override
public void handleRequest() {
adaptee.request();//拥有网线的上网功能,相当于转换连接了
}
}
客户端:电脑
/**
* 客户端类:想要上网,需要连接网线,但是只有USB接口,没有网线接口
*/
public class Computer {
//电脑需要连接上转换器才能上网
public void net(NetToUsb adapter){
//上网的具体实现,转到一个转接头帮我们处理上网请求
adapter.handleRequest();
}
public static void main(String[] args) {
//想要上网,需要电脑、网线、适配器
Computer computer = new Computer();//电脑
Adaptee adaptee = new Adaptee();//网线
// Adapter adapter = new Adapter();//转换器
Adapter2 adapter2 = new Adapter2(adaptee);
computer.net(adapter2);
}
}
输出:
关系图:
对象适配器的优点:
- 一个对象适配器可以把对个不同的适配者适配到同一个目标;
- 可以适配一个适配者的子类,由于适配器和适配者之间是关联的关系,根据“里氏替换原则”,适配者的子类也可以通过该适配器进行适配。
类适配器的缺点:
- 对于Java、C#等不支持多继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;
- 在Java、C#等语言中,类适配器模式的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
使用场景:
- 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的要求,甚至没有这些类的源代码;
- 想创建一些可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
工作中的场景
- 经常用来做旧系统改造和升级
- 如果我们的系统开发之后再也不需要维护,那么很多模式都是没必要的,但是不幸的是,事实却是维护一个系统的代价往往是开发一个系统的数倍。
我们学习中见过的场景
- java.io.InputStreamReader(InputStream)
- java.io.OutputStreamWriter(OutputStream)
源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns
这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23种设计的模式的各种实现方式以及应用场景,非常适用于学习以及提高我们的设计思维,如果对大家有所帮助,请记得star一下给予作者一定的精神支持,你的star是我写出更好的博客的动力,谢谢大家。