DesignPattern - 适配器模式【结构型】

欢迎关注微信公众号:FSA全栈行动 👋java

1、适配器模式介绍

适配器模式(Adapter Pattern)属于结构型模式,做为两个不兼容的接口之间的桥梁。数据库

  • 常见的几类适配器
    • 接口的适配器模式【空实现】:不想实现一个接口中全部的方法时,能够建立一个 Adapter,实现全部方法,在写别的类的时候,继承这个 Adapter 类便可。
    • 类的适配器模式【继承(旧) + 实现(新)】:想将一个类转换成知足另外一个新接口的类时,可使用类的适配器模式,建立一个新类,继承原有的类,实现新的接口便可。
    • 对象的适配器模式【组合】:想将一个对象转换成知足另外一个新接口的对象时,能够建立一个适配器类,持有原类的一个实例,在适配器类的方法中,调用实例的方法就行。
  • 应用场景
    • 电脑须要读取内存卡的数据,读卡器就是适配器
    • 平常使用的转换头,如电源转换头,电压转换头
    • 系统须要使用如今的类,而这些类的接口不符合系统的须要(如:JDK 中 InputStreamReader 就是适配器)
    • JDBC 使用的就是适配器模式,jDBC 给出一个客户端通用的抽象接口,每个具体数据库厂商,如 SQL Server、Oracle、MySQL 等,会开发对应的 JDBC 驱动,这个 JDBC 驱动就是一个介于 JDBC 接口和数据库引擎接口之间的适配器软件。
  • 优势
    • 可让任何两个没有关联的类一块儿运行,使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做
    • 增长灵活度,提升复用性,适配器类能够在多个系统使用,符合开闭原则
  • 缺点
    • 总体类的调用链路增长,原本 A 能够直接调用 C,使用适配器后,是 A 调用 B,B 再调用 C

补充:适配器模式用于设计完成以后,发现类、接口之间没法一块儿工做,须要进行填坑。编程

2、适配器模式代码实现

一、接口适配器模式

有些接口中有多个抽象方法,当咱们写该接口的实现类时,必须实现该接口的全部方法,有时会以为比较冗余,由于并非全部的方法都是咱们须要的,只须要实现部分接口就能够了。微信

建立支付网关接口:markdown

/** * 支付网关接口 * * @author GitLqr */
public interface IPayGateway {

	/** * 下单 */
	void order();

	/** * 退款 */
	void refund();

	/** * 查询 */
	void query();

	/** * 发红包 */
	void sendRedPack();

    ...
}
复制代码

建立接口适配器类:ide

/** * 接口适配器:提供全部接口的默认实现 * * @author GitLqr */
public class PayGatewayAdapter implements IPayGateway {

	@Override
	public void order() {
	}

	@Override
	public void refund() {
	}

	@Override
	public void query() {
	}

	@Override
	public void sendRedPack() {
	}

}
复制代码

建立具体业务类:oop

/** * 视频VIP订购:只有订购和退款功能 * * @author GitLqr */
public class VideoVipOrder extends PayGatewayAdapter {
	@Override
	public void order() {
		System.out.println("视频VIP 订购成功");
	}

	@Override
	public void refund() {
		System.out.println("视频VIP 退款成功");
	}
}
复制代码

说明:相比于实现 IPayGateway 接口,继承 PayGatewayAdapter 适配器类,可让 VideoVipOrder 中代码简洁很多。this

二、类的适配器模式

想将一个类转换成知足另外一个新接口的类时,可使用类的适配器模式,建立一个新类,继承原有的类,实现新的接口便可。spa

建立 旧类:设计

说明:【旧类】对应的是工程中本来就存在的类,可以稳定运行,可是不支持一些新功能。实际开发中,这些旧类实现可能至关复杂(多是屎山),不能轻易改动!!

/** * 旧类:端口,只能支持usb * * @author GitLqr */
public class Port {
	public void usb(Object usbDevice) {
		System.out.println("插入 usb 设备");
	}
}
复制代码

建立 新功能接口:

说明:该【新功能接口】通常拥有 旧类 中的方法,方便后续面向接口编程

/** * 新接口:须要支持旧端口类型(usb)的同时,支持更多的新端口类型(如 typec、usb4) * * @author GitLqr */
public interface INewPort {

	void usb(Object usbDevice);

	void typec(Object typecDevice);

	void usb4(Object usb4Device);
}
复制代码

建立 新类:

说明:【新类】须要继承【旧类】,同时实现【新功能接口】

/** * 新类:端口适配器【扩展坞】 * * @author GitLqr */
public class PortAdapter extends Port implements INewPort {

	@Override
	public void typec(Object typecDevice) {
		System.out.println("插入 type-c 设备");
	}

	@Override
	public void usb4(Object usb4Device) {
		System.out.println("插入 雷电4 设备");
	}

}
复制代码

使用:

public static void main(String[] args) {
	...
    INewPort newPort = new PortAdapter();
    newPort.usb(usbDevice); // 老功能 也能正常使用
    newPort.typec(typecDevice);
    newPort.usb4(usb4Device);
}
复制代码

三、对象的适配器模式

想将一个对象转换成知足另外一个新接口的对象时,能够建立一个适配器类,持有原类的一个实例,在适配器类的方法中,调用实例的方法就行。

对象的适配器更像是一种包装(或加强),实际功能还须要借助原对象来执行处理,就好比充电器插头问题,插头转换器只是改变了充电器插头的类型,实际上给手机充电的,仍是充电器自己。

建立 充电器类:

/** * 充电器 * * @author GitLqr */
public class Charger {

	void charge() {
		System.out.println("充电中...");
	}
}
复制代码

建立 新接口(支持多种插头转换):

/** * 接口:各式插头 * * @author GitLqr */
public interface IPlugConverter {

	/** * 双脚插头充电 */
	void chargeOnTwoPin();

	/** * 三脚插头充电 */
	void chargeOnThreePin();

	/** * 三脚插头充电(港版插座) */
	void chargeOnThreePinHK();

}
复制代码

建立 知足 新接口 的 适配器类:

/** * 充电器插头适配器 * * @author GitLqr */
public class ChargerPlugAdapter implements IPlugConverter {

	private Charger charger;

	public ChargerPlugAdapter(Charger charger) {
		super();
		this.charger = charger;
	}

	@Override
	public void chargeOnTwoPin() {
		charger.charge();
	}

	@Override
	public void chargeOnThreePin() {
		System.out.println("使用三脚插头");
		charger.charge();
	}

	@Override
	public void chargeOnThreePinHK() {
		System.out.println("使用港版三脚插头");
		charger.charge();
	}

}
复制代码

若是文章对您有所帮助, 请不吝点击关注一下个人微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不只有Android技术, 还有iOS, Python等文章, 可能有你想要了解的技能知识点哦~

相关文章
相关标签/搜索