likes
comments
collection
share

适配器模式白话 - 可以用但别多

作者站长头像
站长
· 阅读数 36

前言

设计模式里的适配器模式(Adapter Pattern)还是比较简单的

定义👇

作为两个不兼容的接口之间的桥梁。属于结构型模式,它结合了两个独立接口的功能

比如要拓展电脑屏幕,电脑上是 HDMI 接口,显示器是 VGA 接口,那么需要有个转换器才能把电脑和显示器连起来

上面的 HDMI 和 VGA 就是两个不兼容的接口,转换器就是桥梁

为啥定义里要突出“不兼容”呢?文中揭晓

适配器白话

编译器,像个一丝不苟的规则执行者

当程序员定义了一个A类型的变量,那么提供的实现一定得是A或者A的子类,否则编译会报错

A a = new A();        // √
A a = new AChild();   // √
A a = new B();        // x(B不是A的子类)

适配器模式,像个厚道的中间人——“B不是A的子类,代码编译不通过了是吧。我来做AB的中间人,A有啥事先找我,我再找B”

啥时候用

拿前言里电脑拓展屏幕 HDMI 转 VGA 举例

首先定义一个 VGA 接口并实现它

public interface IVga {
    // VGA信号输入
    void vgaInput();
    // VGA信号输出
    void vgaOutput();
}

public class VgaImpl implements IVga {
    @Override
    public void vgaInput() {
        System.out.println("VGA信号输入");
    }

    @Override
    public void vgaOutput() {
        System.out.println("VGA信号输出");
    }
}

模拟一个只有 VGA 接口的电脑显示器

public interface IMonitor {
    void showVga(IVga vga);
}

public class HuaweiMonitor implements IMonitor {
    @Override
    public void showVga(IVga vga) {
        vga.vgaInput();
    }
}

OK。模拟一下显示器显示 VGA 信号

public class MonitorDisplayDemo {
    public static void main(String[] args) {
        IMonitor monitor = new HuaweiMonitor();
        IVga vga = new VgaImpl();
        monitor.showVga(vga);    // 输出:VGA信号输入
    }
}

接下来要拓展电脑屏幕了

先定义一个 HDMI 接口并实现它

public interface IHdmi {
    void hdmiInput();
    void hdmiOutput();
}

public class HdmiImpl implements IHdmi {
    @Override
    public void hdmiInput() {
        System.out.println("HDMI信号输入");
    }

    @Override
    public void hdmiOutput() {
        System.out.println("HDMI信号输出");
    }
}

重点来了

因为电脑和电脑屏幕已经生产好了,不可能再给它们接口了,所以我们要加个适配器

/**
 * 因为是 HDMI 要适配 VGA,所以适配器实现的是 IVga 接口
 * 此为对象适配器
 */
public class VgaAdapterHdmi implements IVga {
    private IHdmi hdmi;

    public VgaAdapterHdmi(IHdmi hdmi) {
        this.hdmi = hdmi;
    }

    @Override
    public void vgaInput() {
        hdmi.hdmiInput();
    }

    @Override
    public void vgaOutput() {
        hdmi.hdmiOutput();
    }
}

OK。拓展电脑屏幕试试

public class MonitorDisplayDemo {
    public static void main(String[] args) {
        IHdmi hdmi = new HdmiImpl();
        IVga vgaAdapterHdmi = new VgaAdapterHdmi(hdmi);
        monitor.showVga(vgaAdapterHdmi);    // 输出:HDMI信号输入
    }
}

通过新增适配器把 HDMI 和 VGA 结合,没有改动原来的代码,符合开闭原则

为啥定义里要突出“不兼容”?

反向思考一下,假如两个接口兼容

👉 即,顶层协议相同

👉 即,可理解成顶层是同一接口

// 顶层接口
public interface IHardwareInterface {
    void signalInput();
    void signalOutput();
}

// HDMI接口
public interface IHdmi extends IHardwareInterface {
}
// VGA接口
public interface IVga extends IHardwareInterface {
}

// 接口实现
public class HdmiImpl implements IHdmi {
    ...
}
public class VgaImpl implements IVga {
    ...
}

// 调用
public static void main(String[] args) {
    IHardwareInterface hdmi = new HdmiImpl();
    hdmi.signalInput();
    hdmi.signalOutput();

    IHardwareInterface vga = new VgaImpl();
    vga.signalInput();
    vga.signalOutput();
}

都这样了还用啥适配器模式,直接上工厂模式好了

总结

适配器不是在详细设计时添加的,而是解决正在服役的项目的问题,是一种解决方案

就像前面说的,HDMI 和 VGA 的接口已经生产好了不可能再改,这时可以使用适配器

另外,适配器这个“中间人”会增加系统的复杂度,不要过度使用。如果系统在非必要的情况下使用了大量的适配器...果断重构吧骚年😏


感谢阅读~不喜勿喷。欢迎讨论、指正

转载自:https://juejin.cn/post/7221255028894695481
评论
请登录