适配器模式白话 - 可以用但别多
前言
设计模式里的适配器模式(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