通俗易懂的java设计模式之适配器模式

108 阅读3分钟

前段时间呢,买了个插座,专门插空调的,结果插座买小了,原来空调是16a的,插座却是10a的,于是我把空调的插头用钳子掐断了,换了个支持10a的头......

搞错了从来。

我于是在网上买了个插座转换器,嘿嘿问题解决。

回归正文,今天我说的这个适配器模式,就是这样的一个道理。

敲重点了,这个可不能滥用,我要是早知道空调是16a的,直接买个16a的插座不就解决了吗,干嘛在买个适配器,你说是吧。那也许你就有疑惑了,能直接更换个插座解决问题,我干嘛在弄个适配器,其实这就涉及到了一个成本问题,一个插头转换器付出的成本远远小于一个插座的成本(当然你是土豪当我没说)。

接下来,我们把这个插头比喻成一个成熟的接口,插座比喻成一个三方的实现类。这个时候我们要用这个成熟的接口对接三方的一个实现类,对接时发现其中三方实现类的一个方法在接口中并没有实现。你这时会说了,这个还不简单,直接在接口加个方法不就可以了吗,我想说你真是个大聪明。是的,在这个接口加个方法确实能解决问题。但其他实现这个接口的类是不是也需要重写该方法呢,这样是不是就违反了设计五大原则之一的单一职责了,再说了接口是一种规范能随便修改嘛。也许可以让第三方改,但哪个第三方吃饱了撑的管你这事。没办法,只能选择适配,有时不得不向现实低头啊(要充分考虑到成本问题)。

于是你新建了个类专门作为适配器。这个时候又有问题了(怎么有这么多的问题呀),我该怎么适配呢。我怎么让我这个适配器的类去作用到第三方类呢,于是你想到了继承和组合的方式(推荐优先使用组合的方式),在让它实现定义的接口不就完事了吗,这不问题轻轻松松就解决了。

在Mybatis源码中,为了整合三方(五花八门的)日志框架,采用的就是这种适配器模式。

最后附上代码,仅供参考。

public class AdapterMode {

    public static void main(String[] args) {
        new AdapterMode().charge(new StandardAdapter());

        new AdapterMode().charge(new StandardObjAdapter(new ChineseStandard()));

        StandardAdapter standardAdapter = new StandardAdapter(){
            @Override
            public String getBritishStandard() {
                return super.getBritishStandard();
            }
        };
        new AdapterMode().charge(standardAdapter);
    }

    public void charge(BritishStandard britishStandard) {
        if ("中式插座".equals(britishStandard.getBritishStandard())) {
            System.out.println("充电成功!");
        } else {
            System.out.println("充电失败!");
        }
    }

}
//目标角色Target(插座)
class ChineseStandard {
    public String getChineseStandard() {
        return "中式插座";
    }
}
//源角色Adaptee(插头)
interface BritishStandard {
    String getBritishStandard();
}
//类适配器(插头转换器)
//适配器角色 Adapter
class StandardAdapter extends ChineseStandard implements BritishStandard {
    @Override
    public String getBritishStandard() {
        return this.getChineseStandard();
    }
}
//对象适配器
class StandardObjAdapter implements BritishStandard {
    private ChineseStandard chineseStandard;

    public StandardObjAdapter(ChineseStandard chineseStandard){
        this.chineseStandard = chineseStandard;
    }
    @Override
    public String getBritishStandard() {
        return chineseStandard.getChineseStandard();
    }
}

思考:设计模式不能滥用,一定要清楚它的使用场景(说白了不要无知的高调)。

结束!