文档章节

给我一个电源,我便能伴你走天涯 - 适配器模式

 草帽行者
发布于 2016/05/23 16:32
字数 1925
阅读 44
收藏 1
点赞 2
评论 0

#设计模式 - 适配器模式 [toc]

简介

adapter class/object 别名:变压器模式 、包装模式(还包括:装饰模式) 定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作饿两个类能够在一起工作

- 类别

  • 类适配器模式 类适配器模式是通过多重继承实现对一个接口与另一个接口的适配,而这在java中不太适用,所以这里不做讨论
  • 对象适配器 通过组合的方式,将“被适配者”作为一个对象组合到适配器类中,以修改目标接口包装被适配器

输入图片说明

组成角色

  • Targer 目标角色:该角色定义把其他的类转换为何种接口,是已经存在的。换句话说就是客户所期待的接口,可以是具体的、抽象的类或是接口
  • Adaptee 源角色:你想把谁转换成目标角色,“谁”就是源角色,它是已经存在的,运行良好的类或对象
  • Adapter 适配器角色:适配器模式的核心角色,是需要新建的,职责:将源角色 --> 目标角色,怎么转换?通过继承或类关联的方式.

优缺点

  • 优点

    • 可以让任何两个没有关联的类一起运行
    • 提高了类的复用
    • 增加了类的透明度
    • 灵活性好
  • 缺点

    • 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构

适用场合

  • 你想使用一个已经存在的类,而它的接口不符合你的需求。
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口 可能不一定兼容的类)协同工作。
  • (仅适用于对象Adapter) 你想使用一些已经 存在的子类 , 但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

注意事项

  • 在详细设计阶段不要使用,主要出现在维护阶段
  • 与代理模式的区别:
    • 代理模式 --> 不改变原接口
    • 适配器模式 --> 原接口不符合规范

案例

给我一个电源,我便能伴你走天涯

小鸟:“牛哥,公司要我让我到美国的总部去学习,那边有提供电脑,但是我想带上自己的Mac,但是我怕到时不能充电,听说美国那边是低压国家,电压才110V,我国可是220V呢。”

大牛:“放心带着你心爱的本本去吧,记得买个插头转换器就行。”

小鸟:“真的吗?”

大牛:“你把你的充电器拿过来。”

大牛:“你看,你这里的输入电压的范围是:100-240V,输出:20V。这里就表示你本本要的是20V的直流电,这个电源适配器,可以将100-240V范围内的交流电转换成你本本需要的20V的直流电。”

输入图片说明

大牛:“今天再让你涨涨姿势。”

小鸟:“这个我最喜欢了。”

大牛:“你把咱们刚才说的电源适配器用代码写出来看看。”

Target目标角色 --> 充电接口:IVoltageNoteBook

小鸟:“电源适配器与笔记本是通过接口连接的,所以我这里抽象出一个充电的接口类,让笔记本和电源适配器分别去实现它,这样才能愉快的充电”

public interface IVoltageNoteBook {
    // 充电接口
    void voltage20();
}

Target目标角色实现类 --> 笔记本类:NoteBook

小鸟:“笔记本使用的是直流电,方法里面我简单打印出来。”

public class NoteBook implements IVoltageNoteBook{
    @Override
    public void voltage20() {
        // 直流电20V
        int inputVoltage = 20;

        String string = String.format("%s\n\t我是MAC\n\t\t我的额定电压是:20V\n\t已经接通电源,开始充电\n\t\t输入电压:%dV",
                "---------NoteBook----------", inputVoltage);
        System.out.println(string);

    }
}

Adatpee源角色 --> 国家电网:GBVoltageFence

小鸟:“我这里以国家电网为例,使用的是220V的交流电.”

public class GBVoltageFence {
    public int voltage220() {
        System.out.println("\n国家电网,提供220V的电压\n");
        return 220;
    }
}

Adapter角色 --> 国标适配器:GBAdapter

小鸟:“我笔记本要求的是20V的直流电,而国家提供的是220V的交流电,国家是不可能为了我改成直流供电的,如果直接使用220V的电源充电,我就再也见不到我的本本了。就像牛哥你说的,电源适配器就是为了解决这个问题而生的,所以我们这里也来一个电源适配器的类.”

public class GBAdapter implements IVoltageNoteBook {

    private GBVoltageFence gbVoltageFence;

    public GBAdapter(GBVoltageFence gbVoltageFence) {
        this.gbVoltageFence = gbVoltageFence;
    }

    @Override
    public void voltage20() {

        // 调用了不符合要求的交流电:220V
        int inputVoltage = gbVoltageFence.voltage220();

        // 转化算法: 转化为符合要求的20V直流电,将220V --> 20V
        int out = inputVoltage / 10 - 2;

        String string = String.format("%s\n\t我是电源适配器" +
                        "\n\t\t输入的电压范围是:100-240V" +
                        "\n\t已经接通电源,开始充电" +
                        "\n\t\t输入电压:%dV" +
                        "\n\t\t转化后输出的电压:%dV",
                "---------GBAdapter----------", inputVoltage,out);
        System.out.println(string);

    }
}

客户端调用

小鸟:“开始充电了!”

// 如果国家能提供20V的直流电就好了,我就可以直接充电
IVoltageNoteBook iVoltageNoteBook = new NoteBook();
iVoltageNoteBook.voltage20();

// 无奈的现实啊,只能使用220V的交流电充电了
GBVoltageFence volateFenceGB = new GBVoltageFence();
IVoltageNoteBook iVoltage20 = new GBAdapter(volateFenceGB);
iVoltage20.voltage20();

输入图片说明

大牛:“如果,你现在到美国了呢,你要充电咋办?”

小鸟:“我再加一个美国电网类,同时也加一美标适配器类,调用美国电网的供电方法 --> 通过算法转化成需要的20V的直流电,充电的时候,只要将GBVoltageFence --> 美标适配器类就行了。”

大牛:“不错。”

小鸟:“我还知道,我这里用的设计模式是适配器模式,它的精华就在于我的适配类,本来只能使用20V的直流电才能对本本进行充电的,我这里加上它之后,就通过调用其他的类似的但是不太符合要求的事物(国标电网,美标电网),然后进行重设计,达到了我目标要求,就跟我这里先调用国家电网的供电方法voltage220() --> 然后通过算法转化为适合我们本本的充电要求算法一样。”

小鸟:“这样模式适用于项目的维护,在前期的开发中不要考虑,比如说我们这里,在国标适配器中看似调用的是笔记本的充电方法voltage20(),但实际调用的是国家电网提供的voltage220(),这样表里不一,很容易造成混乱,只有在已经运行良好的项目中,系统需要扩展,而原有的接口不符合规范,为了减少代码修改带来风险,我们才考虑使用它,同时项目要遵循依赖倒置原则和里氏替换原则才行,否则这样的话也会带来很大的修改量,还不如重构.”

大牛:“说的好!怪不得你出来不久,你们公司能把去美国学习的机会留给你。”

© 著作权归作者所有

共有 人打赏支持
粉丝 6
博文 28
码字总数 29999
作品 0
广州
程序员
代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho ⋅ 04/09 ⋅ 0

JavaScript设计模式之观察者模式

前言 准备研究一下MVVM的一些东西,由于MVVM运用了观察者模式的思想,因此翻开了《JavaScript设计模式与开发实践》一书,将观察者模式学习了一遍,顺便有对一些常用的设计模式进行一些了解,...

Srtian ⋅ 05/22 ⋅ 0

设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu ⋅ 2017/11/02 ⋅ 0

JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云 ⋅ 05/18 ⋅ 0

系统架构技能之设计模式-单件模式

一、开篇 其实我本来不是打算把系统架构中的一些设计模式单独抽出来讲解的,因为很多的好朋友也比较关注这方面的内容,所以我想通过我理解及平时项目中应用到的一 些常见的设计模式,拿出来给...

wbf961127 ⋅ 2017/11/12 ⋅ 0

Java经典设计模式-结构型模式-适配器模式(Adapter)

适配器模式 适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的...

Idea ⋅ 01/20 ⋅ 0

设计模式.策略模式

策略模式跟抽象工厂非常相似,基本逻辑是根据需要实例化出需要用的类。不同的是策略模式需要调用者非常清晰的知道有哪些策略,各个策略的调用规则,而抽象工厂的话,需要知道有哪些类,找到调...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

[设计模式]简单工厂模式

简介 简单工厂模式 (Simple Factory) 又叫静态工厂方法(Static Factory Method)模式。 简单工厂模式通常是定义一个工厂类,这个类可以根据不同变量返回不同类的产品实例。 简单工厂模式是一...

静默虚空 ⋅ 2015/06/03 ⋅ 0

C#设计模式(2)——简单工厂模式

一、引言   这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信 ⋅ 03/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

spring Email

一、普通邮件 maven依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.6.RELEASE</version>......

BobwithB ⋅ 12分钟前 ⋅ 0

spark 整理的一些知识

Spark 知识点 请描述spark RDD原理与特征? RDD全称是resilient distributed dataset(具有弹性的分布式数据集)。一个RDD仅仅是一个分布式的元素集合。在Spark中,所有工作都表示为创建新的...

tuoleisi77 ⋅ 16分钟前 ⋅ 0

思考

时间一天天过感觉自己有在成长吗?最怕的是时光匆匆而过,自己没有收获!下面总结下最近自己的思考。 认识自己 认识另一个自己,人们常说要虚心听取别人意见和建议。然而人往往是很难做到的,...

hello_hp ⋅ 16分钟前 ⋅ 0

IT行业的变革就像世界杯德国对战墨西哥一样难以预测[图]

最近在观看世界杯,尤其是昨天的比赛,上一届卫冕冠军德国队居然0:1告负墨西哥,这创造了历史,首先是墨西哥从来没赢过德国队,其次是德国队36年来首站没输过,再差也是打平,而这次,德国队...

原创小博客 ⋅ 35分钟前 ⋅ 0

解决CentOS6、7,/etc/sysconfig/下没有iptables的问题

一、Centos 6版本解决办法: 1.任意运行一条iptables防火墙规则配置命令: iptables -P OUTPUT ACCEPT 2.对iptables服务进行保存: service iptables save 3.重启iptables服务: service ...

寰宇01 ⋅ 45分钟前 ⋅ 2

数据库备份和恢复

备份:mysqldump -u root -p 数据库>磁盘路径 恢复:mysql -u root -p 数据库<sql脚本的磁盘路径

anlve ⋅ 今天 ⋅ 0

发生了什么?Linus 又发怒了?

在一个 Linux 内核 4.18-rc1 的 Pull Request 中,开发者 Andy Shevchenko 表示其在对设备属性框架进行更新时,移除了 union 别名,这引发了 Linus 的暴怒。 这一次 Linus Torvalds 发怒的原...

问题终结者 ⋅ 今天 ⋅ 0

在树莓派上搭建一个maven仓库

在树莓派上搭建一个maven仓库 20180618 lambo init 项目说明 家里有台树莓派性能太慢。想搭建一个maven私服, 使用nexus或者 jfrog-artifactory 运行的够呛。怎么办呢,手写一个吧.所在这个...

林小宝 ⋅ 今天 ⋅ 0

Spring发展历程总结

转自与 https://www.cnblogs.com/RunForLove/p/4641672.html 目前很多公司的架构,从Struts2迁移到了SpringMVC。你有想过为什么不使用Servlet+JSP来构建Java web项目,而是采用SpringMVC呢?...

onedotdot ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部