在现实生活中,经常出现两个对象因接口不兼容而不能在一起工作的实例,这时需要第三者进行适配。例如,讲中文的人同讲英文的人对话时需要一个翻译,用直流电的笔记本电脑接交流电源时需要一个电源适配器,用计算机访问照相机的 SD 内存卡时需要一个读卡器等。
在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。
模式的定义与特点
适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式、接口的适配器模式三种,类结构型模式类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
该模式的主要优点如下。
- 客户端通过适配器可以透明地调用目标接口。
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
其缺点是:对类适配器来说,更换适配器的实现过程比较复杂。
模式的结构与实现
类适配器模式可采用多重继承方式实现,如c++可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口;java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。现在来介绍它们的基本结构。
1. 模式的结构
适配器模式(Adapter)包含以下主要角色。
- 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
- 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
A、类适配器模式
结构图
代码如下
package test.adapter;
//目标接口
interface Target{
void request();
}
//适配器接口
class Adapter{
public void specificRequest(){
System.out.println("适配器中的业务代码");
}
}
//类适配器类
class ClassAdapter extends Adapter implements Target{
@Override
public void request() {
specificRequest();
}
}
//客户端代码(测试)
public class ClassAdapterTest{
public static void main(String[] args) {
System.out.println("类适配器模式测试");
Target target=new ClassAdapter();
target.request();
}
}
结果
核心思想就是:有一个Adapter类,拥有一个方法,待适配,目标接口时Targe,通过ClassApdater类,将Adapter的功能扩展到Targe里
B、对象适配器模式
结构图
代码如下
package test.adapter;
//目标接口
interface Target{
void request();
}
//适配器接口
class Adapter{
public void specificRequest(){
System.out.println("适配器中的业务代码");
}
}
//对象适配器类
class ObjectAdapter implements Target{
private Adapter adapter;
public ObjectAdapter(Adapter adapter){
this.adapter=adapter;
}
@Override
public void request() {
adapter.specificRequest();
}
}
public class ObjectAdapterTest {
public static void main(String[] args) {
System.out.println("对象适配器模式测试:");
Adapter adapter=new Adapter();
Target target=new ObjectAdapter(adapter);
target.request();
}
}
结果
C、接口的适配器模式
接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行
结构图
package test.adapter;
interface SourceAble{
void method1();
void method2();
}
//抽象类 Wrapper2
abstract class Wrapper2 implements SourceAble{
public void method1(){
System.out.println("接口适配器测试抽象类方法一");
}
public void method2(){
System.out.println("接口适配器测试抽象类方法二");
}
}
class SourceSub1 extends Wrapper2{
public void method1(){
System.out.println("接口适配器测试方法一");
}
}
class SourceSub2 extends Wrapper2{
public void method2(){
System.out.println("接口适配器测试方法二");
}
}
public class WrapperTest {
public static void main(String[] args) {
SourceAble source1=new SourceSub1();
SourceAble source2=new SourceSub2();
source1.method1();
source1.method2();
source2.method1();
source2.method2();
}
}
结果
总结一下三种适配器模式的应用场景
类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个ObjectAdapter类,持有原类的一个实例,在ObjectAdapter类的方法中,调用实例的方法就行。
接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
来源:CSDN
作者:z446981439
链接:https://blog.csdn.net/z446981439/article/details/104047559