适配器模式

Posted by New Boy on March 15, 2018

前言

说起适配器模式,从字面上理解,还是做到一个适配的功能,笔记本电脑的硬件层面就有个很好的例子,记得刚买笔记本电脑时,特别不习惯笔记本键盘,打dota特别难受,那时候家里台式机上有个键盘,可惜是PS/2接口(就是那种圆形插口),然后去买了个转换口,顺利完成暴走:)。其实罗里吧嗦讲了一堆,还是回到代码层面,在进行代码重构时,老接口我们希望不再进行改动,在其基础上新增功能,就如usb接口一样,我们无法进行修改,这时就需要一个适配类。

适配器模式

适配器主要包括了三种适配器模式,1.类适配器2.对象适配器3.接口适配器。

类适配器

想到这么一个例子,现在有一家公司,公司给员工制定了一些规定,比如上班时不能讲话聊天,现在来了个新的BOSS,新的BOSS懒啊,只想在旧的规定上新增一些规定,比如上班不能吃东西。就这个简单的场景进行了实现。

实现方式是通过继承新接口,继承旧规则,编写新规则来实现。

OldRules:

public class OldRules {
    public void dontTalk() {
        System.out.println("old rule : do not talk...!");
    }
}

NewRules:

public interface NewRules {
    void dontTalk();
    void dontEat();
}

RuleAdapter:

public class RuleAdapter extends OldRules implements NewRules {
    @Override
    public void dontEat() {
        System.out.println("new rule : do not eat...!");
    }
}

测试:

public static void main(String[] args) {
        RuleAdapter adapter = new RuleAdapter();
        adapter.dontEat();
        adapter.dontTalk();
}

对象适配器

就拿上面的情景来说,对象适配器和类适配器其实非常像,不过对象适配器的耦合度要低一些,不需要继承OldRules类,RuleAdapter的实现方式有所区别。

RuleAdapter:

public class RuleAdapter implements NewRules {

    private OldRules oldRules;

    public RuleAdapter(OldRules oldRules) {
        this.oldRules = oldRules;
    }

    @Override
    public void dontTalk() {
        oldRules.dontTalk();
    }

    @Override
    public void dontEat() {
        System.out.println("new rule : do not eat...!");
    }
}

接口适配器(缺省适配器)

其实在接触接口适配器之前,也一直有这么一个疑问,在开发过程中,如果说一个类继承了一个接口,那么必须覆盖这个接口中的所有方法,在一些情景下,肯定是不符合我们的需求的。为此有了一个接口适配器。

比如有个规定的接口,而我只希望实现其中的部分

public interface Rules {
    void dontTalk();
    void dontSmile();
    void dontCry();
    void dontEat();
}

那么可以在实现类和接口之间写一个适配类

public class AbstractRules implements Rules {
    @Override
    public void dontTalk() {}
    @Override
    public void dontSmile() {}
    @Override
    public void dontCry() {}
    @Override
    public void dontEat() {}
}

实现类通过继承该适配类,选择需要重写的方法即可。

说到缺点,还是拿笔记本电脑来说,如果说市场上对这类接口转换器的需求急剧增加,那么作为笔记本电脑厂商,是不是应该考虑电脑的制造呢?在代码层面,适配器的大量使用其实还是不利于代码阅读的,如果时间允许,我觉得重构甚至重写还是有必要的。