设计模式 | 适配器模式(adapter)

定义:

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
 
书中说到Gof的设计模式中,讲了两种类型的适配器模式:
1.类适配器模式
2.对象适配器模式
其中,类适配器模式,是通过多重继承来实现了。
但是Java是不支持多重继承的,所以下面主要讲的是对象适配器模式。
 

结构:(书中图,侵删)

一个客户真正要使用的目标接口(具体一点说可以叫方法),包含它的可以是接口、抽象类、类
一个需要被适配的接口(方法),同上
一个适配器,继承自目标接口,包含一个需要被适配的接口
 

实例:

书中提到一个电源适配器的例子,很形象,所以这里提一嘴。
就是中国的电源是220V,但有的国家是110V,出国之后依旧想使用中国的电器怎么办?就需要用到适配器来转换一下电压。
说到这里,我就想到了一个例子,护照。
中国公民有中国的身份证,外国人也有外国的id card,我们不能指望外国人都用中国的身份证,同样我们也不可能都使用外国的id card。
但是出入境怎么验证你的身份呢,这就需要用到护照,护照就相当于全球通用的身份证。我们这里忽略签证的存在,签证也要盖在护照上不是。
 
目标类(外国身份认证):
package designpattern.adapter;

import java.util.HashSet;
import java.util.Set;

public class ForeignIdentify {
    String socailSecurityNumber;

    // 模拟一个社保号的数据库
    static Set<String> dbSet = new HashSet<>();
    static {
        dbSet.add("F001");
        dbSet.add("F002");
        dbSet.add("F003");
    }

    public boolean check(String socailSecurityNumber) {
        if (dbSet.contains(socailSecurityNumber)) {
            System.out.println(socailSecurityNumber + "是外国的合法公民");
            return true;
        } else {
            System.out.println(socailSecurityNumber + "不是外国的合法公民");
            return false;
        }

    }
}
被适配类(中国身份认证):
package designpattern.adapter;

import java.util.HashSet;
import java.util.Set;

public class ChineseIdentify {
    String idCardNumber;

    // 模拟一个身份证号的数据库
    static Set<String> dbSet = new HashSet<>();
    static {
        dbSet.add("张三C001");
        dbSet.add("李四C002");
        dbSet.add("王五C003");
    }

    public boolean check(String idCardNumber, String name) {
        if (dbSet.contains(name + idCardNumber)) {
            System.out.println(name + idCardNumber + "是中国的合法公民");
            return true;
        } else {
            System.out.println(name + idCardNumber + "不是中国的合法公民");
            return false;
        }

    }
}
适配器(护照):
package designpattern.adapter;

import java.util.HashMap;
import java.util.Map;

public class ChinesePassport extends ForeignIdentify {
    ChineseIdentify chineseIdentify = new ChineseIdentify();

    // 模拟身份证、名字对应数据库
    static Map<String, String> db = new HashMap<>();
    static {
        db.put("C001", "张三");
        db.put("C002", "李四");
        db.put("C003", "王五");

    }

    @Override
    public boolean check(String idCardNumber) {
        // 为了模拟两个接口不完全一样,假设中国的身份验证需要身份证号和名字两个条件
        return chineseIdentify.check(idCardNumber, getName(idCardNumber));
    }

    private String getName(String idCardNumber) {
        return db.get(idCardNumber);
    }
}
客户端:
package designpattern.adapter;

public class Client {
    public static void main(String[] args) {

        ForeignIdentify foreignIdentify = new ForeignIdentify();
        enter("F001", foreignIdentify);
        enter("F004", foreignIdentify);

        // 直接用身份证号来验证
        enter("C003", foreignIdentify);
        // 换成护照
        foreignIdentify = new ChinesePassport();
        enter("C003", foreignIdentify);
    }

    public static void enter(String number, ForeignIdentify foreignIdentify) {
        System.out.println("=============外国入关==============");
        if (foreignIdentify.check(number)) {
            System.out.println("允许入关!");
        } else {
            System.out.println("禁止入关!");
        }

    }
}

结果输出:

=============外国入关==============
F001是外国的合法公民
允许入关!
=============外国入关==============
F004不是外国的合法公民
禁止入关!
=============外国入关==============
C003不是外国的合法公民
禁止入关!
=============外国入关==============
王五C003是中国的合法公民
允许入关!

总结:

这个模式准确的说是一个无奈的选择,不应该当做第一选择,当需要适配的两样东西不好改动的时候,为了让他们能匹配上,才不得不使用适配器。
如果能够提前避免接口不匹配的情况,及时进行代码的重构是更好的选择。就像如果说有电子设备都是同样的充电口,那我们就不需要准备他们多条充电线了。
(0)

相关推荐

  • 2W 字详解设计模式

    重磅干货,第一时间送达 原文链接:javadoop.com/post/design-pattern 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混 ...

  • 常见的设计模式及应用场景

    一.单例模式 单例模式是一种常用的软件设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例. 优点:不会频繁地创建和销毁对象,浪费系统资源. 使用场景:IO ...

  • 如何学习23种设计模式及其思想?

    感觉设计模式是看着简单 ,但是一用就不会,23种设计模式,学的人头大,相信大家都是这样的 设计模式在程序员的面试中会被考到,通常是介绍其原理并说出优缺点.或者对比几个比较相似的模式的异同点.在笔试中可 ...

  • PHP设计模式—适配器模式

    定义: 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口.Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 结构: Target:目标接口,定义与 ...

  • 设计模式-适配器模式

    生活中的例子 如上图所示,生活中适配器无处不在,如电源适配器,读卡器,甚至多转接头读卡器等,都是很常见的例子,它们的目的都是将原本不能一起工作的部件能够在一起工作. 在软件工程领域的适配器也是同样类似 ...

  • 结构型设计模式 -- 适配器模式

    一.小案例分析 1.功能需求: 以电源适配器为例. 一个人去外国旅游,住在外国某宾馆,恰好手机没电(手机是双孔插头),但外国宾馆只有三孔插座,宾馆一般不可能为了旅客,将三孔插座换成双孔插座,此时适配器 ...

  • 设计模式——适配器模式

    适配器模式也叫做包装模式:就是把内部结构包装(适配)成用户期待的格式,使得可以兼容使用 通过继承方式使用适配器模式 /** * @author maikec * @date 2019/5/9 */pu ...

  • 设计模式之适配器模式(adapter pattern)

    适配器主要用于接口的转换或者将接口不兼容的类对象组合在一起形成对外统一接口,是一种结构性模式,其本质是是一个中间件,适用于类及其对象. 本文希望通过简单的介绍和分析,能让读者对适配器模式有一个简单直观 ...

  • 设计模式(七)——适配器模式(SpringMVC框架分析)

    适配器模式1 现实生活中的适配器例子泰国插座用的是两孔的(欧标),可以买个多功能转换插头 (适配器) ,这样就可以使用了. 2 基本介绍1) 适配器模式(Adapter Pattern)将某个类的接口 ...

  • PHP设计模式之适配器模式

    PHP设计模式之适配器模式 这个模式一直以来都有一个很经典的例子,那就是插座!没错,当我们从国外买回来电器,或者旅游出差去国外的时候,经常会需要一个电源适配器,因为我国的电压标准是220伏,而其他国家 ...

  • [PHP小课堂]PHP设计模式之适配器模式

    [PHP小课堂]PHP设计模式之适配器模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 设计模式之适配器模式案例详解

    基本介绍 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作. 适配器模式属于结构性模式,主要分为三类:类适配器模式.对象适 ...