前言

适配器模式是将一个类的接口转换成客户希望的另外一个接口,身边很多东西都是适用于适配器模式的,笔记本的电源(也叫电源适配器),是将220V的交流电转换为笔记本电脑所需要的12V(电流先忽略),笔记本电脑的各种接口,VGA转Hdml,USB-TypeA 转 USB-TypeC,亦或者你在香港买了个手机,充电器是你生活中没见过的三孔插座通过一个转换头转换为国内常用的插头,很多例子都能很形象的解释这个设计模式。适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
UML角色

Source:需要被适配的类、接口、对象,即Datas。
Destination:需要得到的类,Source通过适配得到的类对象,也就是我们期待得到的借口。
Adapter:适配器类,协调Source和Destination,使两者能够协同工作。
适用场景

1,系统需要使用现有的类,但现有的类却不兼容。
2,需要建立一个可以重复使用的类,用于一些彼此关系不大的类,并易于扩展,以便于面对将来会出现的类。
3,需要一个统一的输出接口,但是输入类型却不可预知。
Demo

简单的抽象一个场景:手机充电需要将220V的交流电转化为手机锂电池需要的5V直流电,我们的demo就是写一个电源适配器,将 AC220v ——> DC5V,其实适配器模式可以简单的分为三类:类适配器模式、对象的适配器模式、接口的适配器模式。我们就以这三种模式来实现上述步骤。
类适配器模式

就上面提到的功能,简单的使用类适配器模式,Source类如下:

package com.demo.adapter.classadapter;

/**
 * Created by italkbb on 2018/1/24.
 */

public class AC220 {
    public int output220V(){
        int output = 220;
        return output;
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

我们的目标类Destination,只需要定义方法,由适配器来转化:

package com.demo.adapter.classadapter;

/**
 * Created by italkbb on 2018/1/24.
 */

public interface DC5 {
    int output5V();
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10

Adapter类如下:

package com.demo.adapter.classadapter;

/**
 * Created by italkbb on 2018/1/24.
 */

public class PowerAdapter extends AC220 implements DC5 {
    @Override
    public int output5V() {
        int output = output220V();
        return (output / 44);
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

对于使用,也很简单:

/**
     * 类适配器使用demo
     */
    private void initClassAdapter() {
        DC5 dc5 = new com.demo.adapter.classadapter.PowerAdapter();
        dc5.output5V();
    }

1
    2
    3
    4
    5
    6
    7
    8

因为java单继承的缘故,Destination类必须是接口,以便于Adapter去继承Source并实现Destination,完成适配的功能,但这样就导致了Adapter里暴露了Source类的方法,使用起来的成本就增加了。
对象适配器模式

对于同样的逻辑,我们在以对象适配器模式实现。我们保留AC220和DC5两个基本类,我们让Adapter持有Destination类的实例,然后再实现DC5,以这种持有对象的方式来实现适配器功能:

package com.demo.adapter.objadapter;

import com.demo.adapter.classadapter.AC220;
import com.demo.adapter.classadapter.DC5;

/**
 * Created by italkbb on 2018/1/24.
 */

public class PowerAdapter implements DC5{
    private AC220 mAC220;

public PowerAdapter(AC220 ac220){
        this.mAC220 = ac220;
    }

@Override
    public int output5V() {
        int output = 0;
        if (mAC220 != null) {
            output = mAC220.output220V() / 44;
        }
        return output;
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

使用代码:

/**
     * 对象适配器模式demo
     */
    private void initObjAdapter() {
        com.demo.adapter.objadapter.PowerAdapter adapter = new com.demo.adapter.objadapter.PowerAdapter(new AC220());
        adapter.output5V();
    }

1
    2
    3
    4
    5
    6
    7
    8

对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。再回想装饰者模式,装饰者是对Source的装饰,使用者毫无察觉到Source被装饰,也就是用法不变。而对于适配器模式用法还是有改变的。
接口适配器模式

对于接口适配器模式,我们就不用担着眼于220->5,我们的接口可以有更多的抽象方法,这一点在android开发中有很多影子,动画的适配器有很多接口,但我们只需要关心我们需要的回调方法(详见AnimatorListenerAdapter类),我们把接口比作万能适配器:

package com.demo.adapter.interfaceadapter;

/**
 * Created by italkbb on 2018/1/24.
 */

public interface DCOutput {
    int output5V();
    int output9V();
    int output12V();
    int output24V();
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

然后我们要用的是5V的电压,所以关心5V的适配:

package com.demo.adapter.interfaceadapter;

import com.demo.adapter.classadapter.AC220;

/**
 * Created by italkbb on 2018/1/24.
 */

public class Power5VAdapter extends PowerAdapter {

public Power5VAdapter(AC220 ac220) {
        super(ac220);
    }

@Override
    public int output5V() {
        int output = 0;
        if (mAC220 != null) {
            output = mAC220.output220V() / 44;
        }
        return output;
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

但是我们必须存在一个中间适配器,用于实现默认的接口方法,以至于减少我们适配器的代码量,让代码更加清晰:

package com.demo.adapter.interfaceadapter;

import com.demo.adapter.classadapter.AC220;

/**
 * Created by italkbb on 2018/1/24.
 * 这里抽象类其实就写了空方法,等着子类去实现需要的方法。
 */
public abstract class PowerAdapter implements DCOutput{
    protected AC220 mAC220;

public PowerAdapter(AC220 ac220){
        this.mAC220 = ac220;
    }

@Override
    public int output5V() {
        return mAC220.output220V();
    }

@Override
    public int output9V() {
        return mAC220.output220V();
    }

@Override
    public int output12V() {
        return mAC220.output220V();
    }

@Override
    public int output24V() {
        return mAC220.output220V();
    }
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

这样一来我们就只需要重写父类我们关心的方法了,当然我们有时候可以省略Power5VAdapter类,因为内部类可以实现我们的方法,就跟使用setOnClickOnLintener(new OnClickOnLintener(){…})一样,我们来看使用:

/**
     * 接口适配器模式demo
     */
    private void initinterfaceAdapter() {
        // 已经实现了子类
        com.demo.adapter.interfaceadapter.Power5VAdapter power5VAdapter = new Power5VAdapter(new AC220());
        power5VAdapter.output5V();

// 直接实现子类
        com.demo.adapter.interfaceadapter.PowerAdapter powerAdapter = new PowerAdapter(new AC220()) {
            @Override
            public int output5V() {
                int output = 0;
                if (mAC220 != null) {
                    output = mAC220.output220V() / 44;
                }
                return output;
            }
        };
        powerAdapter.output5V();
    }

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

这样也实现了这个适配功能,而且可以说易于扩展。
总结

可以说Source的存在形式决定了适配器的名字,类适配器就是继承Source类,对象适配器就是持有Source类,接口适配器就是实现Source接口。
后记

android开发中,ListView、RecyclerView等列表展示组件填充数据都会用到Adapter,这里面的Source相当于Datas,Destination相当于Views,然后Adapter去协调数据与显示。使用适配器模式会拥有更高的复用性以及更好的扩展性,但是过多的使用适配器模式,代码的可阅读性会有所下降,但是设计模式应该是对于相对应的情况,而不是盲目的使用。
---------------------
作者:Must_Do_Kaihong
来源:CSDN
原文:https://blog.csdn.net/u012359453/article/details/79165080
版权声明:本文为博主原创文章,转载请附上博文链接!

适配器模式(三种)简单使用相关推荐

  1. 算法:三种简单排序算法

    排序算法比較常见的有:冒泡排序.简单选择排序.直接插入排序:希尔排序.堆排序.归并排序和高速排序算法等. 今天先学习一下前面三种比較简单的算法.排序的相关概念: ①排序的稳定性:两个或多个元素相等.排 ...

  2. 03、三种简单的计时器

    1.计时器在游戏中的使用次数很多,以下是三种简单的计时器写法 2.代码: 1 using System.Collections; 2 using System.Collections.Generic; ...

  3. ajax--跨域问题及三种简单的解决方案

    ajax--跨域问题及三种简单的解决方案 参考文章: (1)ajax--跨域问题及三种简单的解决方案 (2)https://www.cnblogs.com/ddjps/p/10415052.html ...

  4. python中字符串输出的三种简单方式

    python字符串输出的三种简单方式 第一种: 用'+'号进行字符串的拼接,但只限于字符串,不能进行其他类型的拼接.但是可以进行强制类型转换(字符串的强制转换为str(名字)),再用加号进行拼接. 比 ...

  5. Unity 基础 之 实现枚举(enum/Enum)遍历的三种简单方法(foreach/for)

    Unity 基础 之 实现枚举(enum/Enum)遍历的三种简单方法 目录 Unity 基础 之 实现枚举(enum/Enum)遍历的三种简单方法 一.简单介绍 二.实现原理 三.效果预览 四.实现 ...

  6. c语言for循环打印九九乘法口诀的三种简单方法

    c语言for循环打印九九乘法口诀的三种简单方法 由于在学习c语言,今天在复习巩固知识,练习代码的时候,简单的总结了三种for循环打印九九乘法口诀的方法,加深了自己的理解.代码注释和简单的思路已经注释在 ...

  7. 怎么把PDF转换为PPT格式?分享三种简单的转换方法

    怎么把PDF文件转换成PPT格式呢?对于这两种文件格式大家都不陌生,都是在日常办公中常使用的,很多时候我们都需要把文件的格式进行转换才能够使用,这其中就包含将PDF文件转换成PPT格式,很多小伙伴不知 ...

  8. 排序算法(01)— 三种简单排序(冒泡、插入、选择)

    一.概述 排序是数据处理中十分常见且核心的操作,虽说实际项目开发中很小几率会需要我们手动实现,毕竟每种语言的类库中都有n多种关于排序算法的实现.但是了解这些精妙的思想对我们还是大有裨益的. 1.1 排 ...

  9. PDF怎么转换成Word?给大家分享三种简单的转换方法

    我们怎么把拿到手的PDF文件转换成Word文档格式呢?众所周知,PDF文件虽然没有办法能够直接在文件上进行编辑,但是我们可以借助一些编辑软件来实现这一操作,尽管这样还是会有很多小伙伴习惯在Word中来 ...

最新文章

  1. 光影的魔法!Cocos Creator 实现屏幕空间的环境光遮蔽(SSAO)
  2. 在Ubuntu下成功搭建以太坊私有链挖矿并转账
  3. 大数系列三——斐波那契数列——高效万进制,亿进制
  4. 跳台阶游戏(洛谷P5613题题解,Java语言描述)
  5. python编程入门视频-Python编程入门电子书及视频教程-非常详细『强烈推荐』
  6. nginx fastcgi python_Nginx+FastCGI+Python
  7. 无线通信设备安装工程概预算编制_建筑安装工程,预算编制中易遗漏总结分享...
  8. vmware tools的下载与安装
  9. PS修改证件照照背景颜色(带毛发)
  10. python股票量化交易学习目录
  11. 英文论文写作小贴士(2)
  12. 用模拟退火算法估价heston期权定价模型的五个参数
  13. glob patterns
  14. Hex编码与Base64编码
  15. 软件工程复习笔记——项目计划
  16. Excel 调用百度翻译API进行翻译
  17. Tight WCRT Analysis of Synchronous C Programs
  18. 弃用手机号码未被解绑小米账户:用户信息遭泄露
  19. 关于储备(应急储备、管理储备、储备分析)的总结讨论
  20. 鱼眼镜头拍摄全景图的教程方法

热门文章

  1. 模拟电视频率可用于超级Wi-Fi
  2. Windows 2008 R2+iis7.5环境下Discuz!X3论坛伪静态设置方法
  3. linux c socket programming
  4. Windows 到 Linux 之旅: 第 8 部分. 备份与恢复
  5. 【LintCode: 3. 统计数字】算法题解析
  6. nginx调用PHP有sock方式和端口方式
  7. elasticsearch数据长期保存的方案
  8. 鱼缸式百分比信息图表,这样计算才正确
  9. linux下memcached安装 和redis安装,jdk,tomcat,mysql 安装
  10. centos 网卡配置(入门级)