设计模式之适配器模式

110 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

简介

今天咱们开始结构型设计模式的学习,开篇第一讲是适配器模式。

适配器模式的定义是:

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作

通俗来说适配器的作用是让我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。

案例

类适配器

这一实现使用了继承机制: 适配器同时继承被适配者。

被适配类。即你想把谁转换成目标角色,这是一个已经存在的,但是不满足目标类直接调用的类

public class NetWork {
    public void surf(){
        System.out.println("surf");
    }
}

定义适配器类的接口方法

public interface IAdapter {
    void surf();
}

适配器模式的核心角色,即中间的适配器,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:通过继承或是类关联的方式把源角色转换为目标角色,它充当一个转换器,一个桥梁的作用。

public class Adaptor extends NetWork implements IAdapter {
    @Override
    public void surf() {
        super.surf();
    }
}

该角色定义把其他类转换为何种接口,也就是我们的期望接口,即要达成目的的类

public class Computer {
    public void surfOnLine(IAdapter adapter) {
        adapter.surf();
    }
}

测试类

public class App {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.surfOnLine(new Adaptor());
    }
}

对象适配器

对象适配器其他条件和类适配器一致,只不过我们不是通过继承被适配类来实现调用,而是通过组合的方式,将被适配类以成员变量的方式提供给适配器进行适配。

public class Adaptor implements IAdapter {
    private NetWork netWork;
    public Adaptor(NetWork netWork) {
        this.netWork = netWork;
    }
    @Override
    public void surf() {
        netWork.surf();
    }
}

测试类

public class App {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.surfOnLine(new Adaptor(new NetWork()));
    }
}

总结

  • 符合单一职责原则,你可以将数据适配和转换的代码从业务逻辑中剥离出来,实现解耦。
  • 满足开闭原则,只要客户端代码通过客户端接口与适配器进行交互, 而且通过这种方式我们还能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。得益于我们定义了IAdapter接口。
  • 但是通过引入设计模式,代码整体复杂度增加,代码量明显增加,因为你需要新增一系列接口和类。有时直接更改服务类使其与其他代码兼容会更简单。所以设计模式还是需要经过考量来使用,不能为了套设计模式而使用,这样反而会很牵强,然代码阅读者更加费解。

PS:虽然大致理解了适配器模式的使用场景,但是对于这种示例我还是抱有一定的疑问,比如为啥要加一个中间的适配器在里面,直接将NetWork类组合或者继承到Computer类不就搞定了吗? 我的理解既然是接口不适配就应该是目标类的目标方法的入参和被适配类的被适配方法的返回值不适配。这样才需要用到适配器模式,对被适配器方法的返回值进行适配,适配为目标方法的入参。

所以按照这种思想,那真正比较合适的代码示例应该如下:

Computer类,即目标类,目标方法的入参是Usb

public class Computer {
    public void surfOnLine(Usb usb) {
        System.out.println(usb.getMsg());
    }
}

NetWork类,即需要被适配的类,其出参数是Net

public class NetWork {
    public Net surf(){
        return new Net("Hello");
    }
}

如果仅仅通过以上两个类我们调用Computer类是无法上网的,故我们要引入中间适配器类

public interface IAdapter {
    Usb transfer(Net net);
}
public class Adaptor extends NetWork implements IAdapter {
    @Override
    public Usb transfer(Net net) {
        return new Usb(net.getMsg());
    }
}

适配器类通过将被适配的方法的返回值Net转换成目标方法的入参Usb

测试类

public class App {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.surfOnLine(new Adaptor().transfer(new NetWork().surf()));
    }
}

以上才算完成了适配器模式的完整应用。

个人愚见,望指正。