设计模式-适配器模式

2022-10-09 20:43:43 浏览数 (1)

什么是适配器模式?

将一个类的接口转换成客户希望的另外一个接口。

Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作

适配器模式中的角色分析

目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

需要适配的类(Adaptee):需要适配的类或适配者类。

适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。

image.pngimage.png

从结构图可以看出,Adaptee类并没有method2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,我们把Adaptee与Target衔接起来。Adapter与Adaptee是继承关系,这决定了这是一个类适配器模式。

这里写图片描述

实现方式

1、类适配器(采用继承实现)

因为 Adapter 类既继承了 Adaptee (被适配类),也实现了 Target 接口(因为 Java 不支持多继承,所以这样来实现)所以被称为类适配器。

(以插网线上网举例):

1)首先我们拥有一根网线,他有上网的功能,但是它的接口与电脑不匹配

代码语言:txt复制
//要适配的类:网线
代码语言:txt复制
public class Adaptee {
代码语言:txt复制
    //功能:上网
代码语言:txt复制
    public void request(){
代码语言:txt复制
        System.out.println("链接网线上网");
代码语言:txt复制
    }
代码语言:txt复制
}

2)因此我们定义了一个usb接口,也就是上面提到的目标接口(Target)

代码语言:txt复制
//接口转换器的抽象实现
代码语言:txt复制
public interface NetToUsb {
代码语言:txt复制
    //作用:处理请求,网线=>usb
代码语言:txt复制
    public void handleRequest();
代码语言:txt复制
}

3)定义一个适配器继承着网线,连接着usb接口

代码语言:txt复制
//真正的适配器,余姚链接usb,连接网线
代码语言:txt复制
public class Adapter extends Adaptee implements NetToUsb {
代码语言:txt复制
    @Override
代码语言:txt复制
    public void handleRequest() {
代码语言:txt复制
        super.request();//可以上网了
代码语言:txt复制
    }
代码语言:txt复制
}

4)上网的具体实现

代码语言:txt复制
//客户端类:想上网,插不上网线
代码语言:txt复制
public class Computer {
代码语言:txt复制
    //电脑需要连接上转接器才可以上网
代码语言:txt复制
    public void net(NetToUsb adapter){
代码语言:txt复制
        //上网的具体实现:找一个转接头
代码语言:txt复制
        adapter.handleRequest();
代码语言:txt复制
    }
代码语言:txt复制
    public static void main(String[] args) {
代码语言:txt复制
        //电脑,适配器,网线
代码语言:txt复制
        Computer computer = new Computer();//电脑
代码语言:txt复制
        Adapter adapter = new Adapter();//转接器
代码语言:txt复制
        computer.net(adapter);//电脑直接连接转接器就可以
代码语言:txt复制
    }
代码语言:txt复制
}

缺点 :

对于java,c#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不同同时适配多个适配者

在java,c#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性

2、对象适配器(委托方式实现)

不是使用多继承或继承再实现的方式,而是使用直接关联,或者称为委托的方式

1)更改适配器为如下代码

代码语言:txt复制
public class Adapter2 implements NetToUsb {
代码语言:txt复制
    private Adaptee adaptee;
代码语言:txt复制
    public Adapter2(Adaptee adaptee){
代码语言:txt复制
        this.adaptee = adaptee;
代码语言:txt复制
    }
代码语言:txt复制
    @Override
代码语言:txt复制
    public void handleRequest() {
代码语言:txt复制
    adaptee.request();;//可以上网了
代码语言:txt复制
    }
代码语言:txt复制
}

2)此时的客户端中,转接器需要分别连接网线和电脑

代码语言:txt复制
//客户端类:想上网,插不上网线
代码语言:txt复制
public class Computer {
代码语言:txt复制
    //电脑需要连接上转接器才可以上网
代码语言:txt复制
    public void net(NetToUsb adapter){
代码语言:txt复制
        //上网的具体实现:找一个转接头
代码语言:txt复制
        adapter.handleRequest();
代码语言:txt复制
    }
代码语言:txt复制
    public static void main(String[] args) {
代码语言:txt复制
        //电脑,适配器,网线
代码语言:txt复制
        Computer computer = new Computer();//电脑
代码语言:txt复制
        Adaptee adaptee = new Adaptee();//网线
代码语言:txt复制
        Adapter2 adapter2 = new Adapter2(adaptee);//转接器
代码语言:txt复制
        computer.net(adapter2);
代码语言:txt复制
    }
代码语言:txt复制
}

优点

一个对象适配器可以把多个不同的适配者适配到同一个目标

可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据’里氏替换原则’适配者的子类也可以通过该适配器进行适配

使用场景

系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码

像创建一个重复使用的类,用于与一些彼此之间没有太大联系的类,包括一些可能在将来一起工作的类

比如GUI编程,springboot

0 人点赞