设计模式——适配器(Adapter)模式

  • 概述

  什么是适配器?在我们生活中的适配器比如插头转换器(中标转美标)、USB接口转换器(type-c转苹果),电脑电源适配器(交流电转低电压直流)等。像这种将两者有差异的东西通过适配器使他们成为相互适合的东西。在程序世界中,经常存在现有的程序无法直接使用,需要做适当的变换后才能使用的情况,这种用于填补“现有程序”和“所需程序”之间差异的设计模式就是适配器(Adapter)模式。适配器模式有类适配器模式和对象适配器模式两种,前者使用继承,后者使用组合,所以后者比较灵活,推荐使用。下面通过实例对这两种模式的学习做一个笔记。

  • 实例

  类适配器模式

  Banner类:代表现在的实际情况

/**
 * 注意:两种实现方式都是用的这个Banner类
 * 推荐使用对象适配器方式
 */
public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }

    /**
     * 用括号将字符串括起来
     */
    public void showWithParen(){
        System.out.println("("+string+")");
    }

    /**
     * 用星号将字符串括起来
     */
    public void showWithAster(){
        System.out.println("*"+string+"*");
    }
}

  PrintForClass接口:代表是“需求”的接口

public interface PrintForClass {
    public abstract  void printWeak();
    public abstract  void printStrong();
}

  PrintBannerForClass类:扮演适配的角色。

  实现目标接口(PrintForClass)达到适配目的,而继承被适配者类(Banner)达到通过调用被适配者里的方法来实现目标接口的功能。

public class PrintBannerForClass extends  Banner implements PrintForClass{


    public PrintBannerForClass(String string) {
        super(string);
    }

    //实现PrintForClass中的方法
    @Override
    public void printWeak() {
        super.showWithParen();
    }

    @Override
    public void printStrong() {
        super.showWithAster();
    }
}

  Main类:通过扮演适配器角色的PrintBannerForClass类来显示字符串。

  注意:这里我们将PrintBannerForClass类的实例保存在了PrintForClass类型的变量中。在这个类中,我们是使用PrintForClass接口来进行编程的。对Main类来说,Banner类、showWithParen()、showWithAster()方法被完全隐藏起来了。这就好像电脑电源适配器(交流电转低电压直流),电脑使用的是直流电,而它并不关心这个直流电是怎么来的。

public class Main {
    public static void main(String[] args) {
        //使用类适配器模式(继承)
        PrintForClass p = new PrintBannerForClass("Hello World!");
        p.printWeak();
        p.printStrong();
   }
}

  对象适配器模式(推荐

  对象适配器模式就是采用一种“委托”的方式将某个方法中的实际处理交给其它实例来处理。在下面的例子中就是当PrintBannerForObject类中的printWeak()方法被调用的时候,并不是PrintBannerForObject类自己进行处理,而是将处理交给了Banner类的实例的showWithParen()方法。

  Banner类:和上面的Banner类一样

  PrintForObject类:不同于使用类适配器模式,这里使用的类,而类适配模式是使用的接口。

public abstract  class PrintForObject {
    public abstract  void printWeak();
    public abstract  void printStrong();
}

  PrintBannerForObject类:这个类中的banner字段保存了Banner的实例。然后printWeak()方法和printStrong()方法通过这个实例对象调用Banner类中的方法实现具体的功能。

public class PrintBannerForObject extends PrintForObject {
    private Banner banner;

    public PrintBannerForObject(String string) {
        this.banner = new Banner(string);
    }

    //实现PrintForObject中的方法
    @Override
    public void printWeak() {
        banner.showWithParen();
    }

    @Override
    public void printStrong() {
        banner.showWithAster();
    }
}
  • 完整代码

  请移步:https://github.com/yyc007/DesignPatterns/

  • 小结

  适配器模式就是将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容。

  从用户的角度看不到被适配者,是解耦的;

  用户调用适配器转化出来的目标接口方法;

  适配器再调用被适配者的相关接口方法;

  用户收到反馈结果,感觉只是和目标接口交互。

posted @ 2018-12-14 19:55  敲代码的小松鼠  阅读(419)  评论(0编辑  收藏  举报

你若不想做,总会找到“接口”;你若想做,总会找到“方法”。