欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式学习 - 适配器模式

程序员文章站 2022-06-13 12:32:46
...

适配器模式简介

定义

适配器模式又称之包装模式,将一个类的接口转换成用户所希望的接口,可以使原本两个不相互兼容的类在一起工作。
可以通俗理解为,适配器模式就是把目标理想变成现实的。

UML类结构图

适配器模式分为类适配器模式和对象适配器模式,两者的UML类图有点细微的区别。

类适配器模式
设计模式学习 - 适配器模式

对象适配模式
设计模式学习 - 适配器模式

从上图可以看出,类适配模式与对象适配器区别主要体现在Adapter与Adaptee的关系不同。

  • 类适配器模式:是通过继承关系把Adaptee与Adapter连接到一起。
  • 对象适配器模式:是以委托代理的方式连接到一起,用户通过对象传递的方式进行关联。

角色介绍:

  • Target:目标角色,用户理想中的接口,这里目标接口是YaoMing
  • Adaptee:被适配的类,实现情况下的接口,这里被适配的类是JiaoLian
  • Adapter:适配转换器,是理想目标实现的方式,是一个具体类,是整个适配器模式的核心。

下面通过简单的例子,再结合UML图就能够很好的理解适配器模式是什么样子。

适配器模式的简单实现

据说,姚明刚刚去NBA打球时,有记者采访姚明说:“在CBA和NBA最大的区别是什么?”,姚明的答案是“在NBA我需要翻译,而在CBA我不需要”,可见姚明刚开始是不懂外语的,在比赛中,怎样听懂明白教练的战术安排,此时就需要找到一个中间人进行翻译,把教练的话翻译成中文,姚明就可以听懂了。

  • 姚明希望听到的是中文,就是Target目标接口
  • 实际上教练讲的是英文,就是被适配Adaotee类。
  • 中间人翻译,把英文翻译成中文的过程,就是Adapter类

代码实现

1、创建用户希望的目标YaoMing接口,姚明希望能听到中文。

/**
 * 
 * @author 13480
 * 目标类(用户所期待的样子),
 * 姚明希望听到是中文话。
 */
public interface YaoMing {

    String getChinese();

}

2、创建一个需被适配的类Adaptee。

/**
 * 
 * @author 13480
 * Adaptee类,需要被适配的类
 * 需要教练本身讲的是英文,姚明听不懂,这时教练说的话就要被翻译成中文,姚明才能听懂,这就是被适配的类
 */
public class JiaoLian {

    //教练战术安排,要求姚明加强防守
    public String english(){
        return "Yao Ming strengthens defense";
    }
}

3、创建中间翻译人Adapter,这里分成类适配器模式和对象适配器模式进行对比

(1)类适配器模式的Adapter

public class TranslatorAdapter extends JiaoLian implements YaoMing{

    @Override
    public String getChinese() {
        String english = english();
        System.out.println("JiaoLian:"+english);
        //中间省略……翻译过程 english --> chinese
        String chinese="姚明加强防守";
        return chinese;
    }

}

(2)对象适配器模式的Adapter

public class TranslatorAdapter2  implements YaoMing{

    private JiaoLian mJiaoLian;

    public void setJiaoLian(JiaoLian mJiaoLian) {
        this.mJiaoLian = mJiaoLian;
    }

    @Override
    public String getChinese() {
        String english = mJiaoLian.english();
        System.out.println("JiaoLian:"+english);
        //中间省略……翻译过程 english --> chinese
        String chinese="姚明加强防守";
        return chinese;
    }

}

4、用户端使用

public class AdapterTest {

    public static void main(String[] args) {
        //类适配器模式使用
        TranslatorAdapter translatorAdapter = new TranslatorAdapter();
        System.out.println("翻译的结果:"+translatorAdapter.getChinese());

        //对象适配器模式使用
        JiaoLian jiaoLian = new JiaoLian();
        TranslatorAdapter2 translatorAdapter2 = new TranslatorAdapter2();
        translatorAdapter2.setJiaoLian(jiaoLian);
        System.out.println("翻译的结果:"+translatorAdapter2.getChinese());
    }

}

输出结果:

JiaoLian:Yao Ming strengthens defense
翻译的结果:姚明加强防守

从实现中可以看出,对象适配器是对象传递来实现关联的,因此可以适配多个对象,而类适配器则是通过继承来关联的,由于java中只能单继承,所以无法做到动态修改,只能适配一个类;除此之外,适配器类由于继承于被适配器类,会把被适配类的属性方法暴露出来,会造成潜在使用安全问题。因此开发中更多的是选择对象适配器方式实现,更灵活又安全。

使用场景

  • 往往在项目后期维护中,旧接口不太符合新需求的要求,而又不想创建新对象来实现,想复用旧接口,此时可以用适配器模式进行包装。
  • 需要一个统一的输出接口,而用户端输入又是一个未知的类型。在Android最典型的就是ListView的适配器,适配器暴露getView接口,来满足用户各种各样的样式布局。