Adapter模式

在程序世界中,经常会存在现有的程序无法直接使用,需要做适当的变换后才能使用的情况。这种用于填补“现有的程序”和“所需的程序”之间差异的设计模式就是Adapter模式
Adapter模式分为两种:

  • 类适配器模式(使用继承的适配器)
  • 对象适配器模式(使用委托的适配器)

使用继承的适配器

示例

Banner类是现有的程序,Print接口则是所需的程序,PrintBanner类则是我们的适配器。该类继承了Banner并实现了“需求”--Print接口
20210901151124

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 + "*");
    }
}

Print接口

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

PrintBanner类

public class PrintBanner extends Banner implements Print {
    public PrintBanner(String string) {
        super(string);
    }
    public void printWeak() {
        showWithParen();
    }
    public void printStrong() {
        showWithAster();
    }
}

Main类

public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printWeak();
        p.printStrong();
    }
}

这里将PrintBanner类的实例保存在了Print类型的变量中。在Main中,我们是使用Pring接口来编程的,对于Main类的代码而言,Banner类及其方法被完全隐藏起来,且Main并不知道PrintBanner是如何实现的,这样就可以在不用对Main类进行修改的情况下改变PrintBanner类的具体实现

使用委托的适配器

示例

在Java语言中,委托就是将某个方法中的实际处理交给其他实例的方法。
20210901232333
Main类与Banner类不变

Print类

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

PrintBanner类

public class PrintBanner extends Print {
    private Banner banner;  //实际处理者
    public PrintBanner(String string) {
        this.banner = new Banner(string);
    }
    public void printWeak() {
        banner.showWithParen();
    }
    public void printStrong() {
        banner.showWithAster();
    }
}

Adapter模式中的登场角色

Target(对象)

该角色负责定义所需的方法,即所需程序,在示例中,由Print接口(抽象类)扮演此角色

Client(请求者)

该角色负责使用Target角色所定义的方法进行具体处理,在示例中,由Main类扮演此角色

Adaptee(被适配)

Apaptee是一个持有既定方法的角色,即现有的程序,在示例中,由Banner类扮演此角色。
如果Adaptee角色中的方法与Target角色的方法相同,就不需要接下来的Adapter角色了。

Adapter(适配)

Adapter模式的主人公。使用Adaptee角色的方法来满足Target角色的需要,这就是Adapter模式的目的,也是Adapter角色的作用。在示例中,由PrintBanner类扮演这个角色。

类适配器模式的类图(使用继承)

20210901233554

对象适配器模式的类图(使用委托)

20210901233716

为什么要使用Adapter模式

如果某个方法就是我们所需要的方法,那么直接在程序中使用不就可以了,为什么还要考虑使用Adapter模式?

很多时候,我们并非从零开始编程,经常会用到现有的类。特别是当现有的类已经被充分测试过了,Bug很少,而且已经被用于其他软件中时,我们更愿意将这些类作为组件重复使用、
Adapter模式会对现有的类进行适配,生成新的类。通过该模式可以很方便地创建我们需要的方法群。当出现Bug时,由于我们很明确的知道Bug不在现有的类(Adaptee)中,所以只需检查Adapter角色的类即可。
此外,使用Adapter模式可以在完全不改变现有代码的前提下是现有代码适配于新的API。
当然,功能完全不同类是无法使用该模式的

Q.E.D.


励志成为年薪百块工程师