1、什么是适配器模式?

适配器如同一个常见的变压器,也如同电脑的变压器和插线板之间的电源连接线,他们虽然都是3相的,但是电脑后面的插孔却不能直接插到插线板上。

如果想让额定工作电压是直流12伏特的笔记本电脑在交流100伏特”的AC电源下工作,应该怎么做呢?通常,我们会使用AC适配器,将家庭用的交流100伏特电压转换成我们所需要的直流12伏特电压。这就是适配器的工作,它位于实际情况与需求之间,填补两者之间的差异。适配器的英文是Adapter,意思是.....相互适合的东西”。前面说的AC适配器的作用就是让工作于直流12伏特环境的笔记本电脑适合于交流100伏特的环境(如下图)。

在程序世界中,经常会存在现有的程序无法直接使用,需要做适当的变换之后才能使用的情况。这种用于填补“现有的程序”和“所需的程序”之间差异的设计模式就是Adapter模式。Adapter模式也被称为Wrapper模式。Wrapper有 “包装器”的意思,就像用精美的包装纸将普通商品包装成礼物那样,替我们把某样东西包起来,使其能够用于其他用途的东西就被称为“包装器”或是“适配器”。

Adapter模式有以下两种。

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

本章将依次学习这两种Adapter模式。

2、适配器样例

首先定义一个Banner类,比如就是我们实际的情况.

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:21
* @Description TODO
*/
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接口, 是需求的接口

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:24
* @Description TODO
*/
public interface Print {
   public abstract void printWeak();    public abstract void printStrong(); }

2.1、类适配器模式

定义一个PrintBanner类,扮演适配器的角色 它继承Banner并且实现Print接口.

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:25
* @Description TODO
*/
public class PrintBanner extends Banner implements Print {    public PrintBanner(String string) {
       super(string);
  }    @Override
   public void printWeak() {
       showWithParen();
  }    @Override
   public void printStrong() {
       showWithAster();
  }
}

Main测试类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:26
* @Description TODO
*/
public class Main1 {
   public static void main(String[] args) {
       PrintBanner p1 = new PrintBanner("hello world");
       p1.printWeak();
       p1.printStrong();
  }
}

运行结果如下:

(hello world)
*hello world*

2.2、对象适配器模式

定义一个BasePrint抽象类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:24
* @Description TODO
*/
public abstract class BasePrint {
   public abstract void printWeak();    public abstract void printStrong(); }

定义一个PrintBanner2类,它继承BasePrint

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020/7/14 22:10
* @Description TODO
*/
public class PrintBanner2 extends BasePrint {
   Banner banner;    public PrintBanner2(String string) {
       this.banner = new Banner(string);
  }    @Override
   public void printWeak() {
       banner.showWithParen();
  }    @Override
   public void printStrong() {
       banner.showWithAster();
  }
}

定义Main2测试类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020/7/14 22:11
* @Description TODO
*/
public class Main2 {
   public static void main(String[] args) {
       PrintBanner2 p2 = new PrintBanner2(" main2 ");
       p2.printWeak();
       p2.printStrong();
  }
}

运行结果如下:

( main2 )
* main2 *

3、适配器的登场角色

类适配器模式:

对象适配器模式

◆Target(对象)

该角色负责定义所需的方法。以本章开头的例子来说,即让笔记本电脑正常工作所需的直流12伏特电源。在示例程序中,由Print接口(使用继承时)和Print类(使用委托时)扮演此角色。

◆Client (请求者)

该角色负责使用Target 角色所定义的方法进行具体处理。以本章开头的例子来说,即直流12伏特电源所驱动的笔记本电脑。在示例程序中,由Main类扮演此角色。

◆Adaptee (被适配)

注意不是Adapt-er (适配)角色,而是Adapt-ee (被适配)角色。Adaptee是-一个持有既定方法的角色。以本章开头的例子来说,即交流100伏特电源。在示例程序中,由Banner类扮演此角色。如果Adaptee角色中的方法与Target角色的方法相同(也就是说家庭使用的电压就是12伏特直流电压),就不需要接下来的Adapter角色了。

◆Adapter (适配)

Adapter模式的主人公。使用Adaptee角色的方法来满足Target 角色的需求,这是Adapter 模式的目的,也是Adapter角色的作用。以本章开头的例子来说,Adapter 角色就是将交流100伏特电压转换为直流12伏特电压的适配器。在示例程序中,由PrintBanner类扮演这个角色。在类适配器模式中,Adapter角色通过继承来使用Adaptee角色,而在对象适配器模式中,Adapter角色通过委托来使用Adaptee角色。

4、什么时候使用适配器?

一定会有读者认为“如果某个方法就是我们所需要的方法,那么直接在程序中使用不就可以了吗?为什么还要考虑使用Adapter模式呢?”那么,究竟应当在什么时候使用Adapter模式呢?

很多时候,我们并非从零开始编程,经常会用到现有的类。特别是当现有的类已经被充分测试过了,Bug很少,而且已经被用于其他软件之中时,我们更愿意将这些类作为组件重复利用。

Adapter模式会对现有的类进行适配,生成新的类。通过该模式可以很方便地创建我们需要的方法群。当出现Bug时,由于我们很明确地知道Bug不在现有的类( Adaptee角色)中,所以只需调查扮演Adapter角色的类即可。这样一来, 代码问题的排查就会变得非常简单。

5、总结

个人经验

如何做到一个类不被实例化或者不被轻易实例化?

1.把一个类定义为抽象类;

2.把一个类的构造方法设置为:private类型的,这样在客户端就不能通过new ClassName()方法来轻易将一个类实例化,而要生成此类的实例就必须通过一个特殊的方法,这样在一个系统中,对此类的使用就能得到合理的控制(如:单例模式/多例模式/简单工厂方法等模式)。

3. 对于两个独立的系统,要满足ocp原则,则适配器模式会有一定的局限性。

发哥讲

如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~

● 扫码关注公众号

2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式的更多相关文章

  1. 11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式

    1.Composite模式定义 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这 ...

  2. 设计模式--适配器(Adapter)模式

    今天学习另一个设计模式,适配器(Adapter)模式,这是一个共同方向,但有特殊要求,就应用到此设计模式.写到这里,想起很久以前,有写过一篇<ASP.NET的适配器设计模式(Adapter)&g ...

  3. 【原】模式之-适配器Adapter模式

    适配器Adapter模式 适配器模式(Adapter Pattern)把一个类的接口变换成客户端所期待的的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 模式所涉及的角色有 ...

  4. 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)

      桥接模式Bridge   Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来   意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展.  意图解析 依赖倒置原 ...

  5. 适配器模式 adapter 结构型 设计模式(九)

    现实世界中的适配器模型   先来看下来几个图片,截图自淘宝 上图为港版的插头与港版的插座   上图为插座适配器卖家的描述图   上图为适配后的结果 现实世界中适配器模式 角色分类 这就是适配器模式在电 ...

  6. 代理模式 PROXY Surrogate 结构型 设计模式(十四)

    代理模式 PROXY 别名Surrogate 意图 为其他的对象提供一种代理以控制对这个对象的访问. 代理模式含义比较清晰,就是中间人,中介公司,经纪人... 在计算机程序中,代理就表示一个客户端不想 ...

  7. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  8. 组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)

    组合模式(合成模式 COMPOSITE) 意图 将对象组合成树形结构以表示“部分-整体”的层次结构. Composite使得用户对单个对象和组合对象的使用具有一致性.   树形结构介绍 为了便于理解, ...

  9. java演示适配器(adapter)模式

    为什么要使用模式: 模式是一种做事的一种方法,也即实现某个目标的途径,或者技术. adapter模式的宗旨就是,保留现有类所提供的服务,向客户提供接口,以满足客户的需求. 类适配器:客户端定义了接口并 ...

随机推荐

  1. java 基本语法(十二) 数组(五)Arrays工具类的使用

    1.理解:① 定义在java.util包下.② Arrays:提供了很多操作数组的方法. 2.使用: //1.boolean equals(int[] a,int[] b):判断两个数组是否相等. i ...

  2. cnn卷积理解

    首先输入图像是28*28处理好的图. 第一层卷积:用5*5的卷积核进行卷积,输入为1通道,输出为32通道.即第一层的输入为:28*28图,第一层有32个不同的滤波器,对同一张图进行卷积,然后输出为32 ...

  3. web前端 javascript 兼容低版本 IE 6 7 8复合写法

    1. 返回检测屏幕宽度(可视区域) function client() { if(window.innerWidth != null) // ie9 + 最新浏览器 { return { width: ...

  4. 你有认真了解过自己的“Java对象”吗? 渣男

    对象在 JVM 中是怎么存储的 对象头里有什么? 文章收录在 GitHub JavaKeeper ,N线互联网开发必备技能兵器谱,有你想要的. 作为一名 Javaer,生活中的我们可能暂时没有对象,但 ...

  5. Ethical Hacking - NETWORK PENETRATION TESTING(23)

    Detecting ARP Posionning Attacks ARP main security issues: 1. Each ARP requests/response is trusted. ...

  6. C# 泛型中的数据类型判定与转换

    提到类型转换,首先要明确C#中的数据类型,主要分为值类型和引用类型: 1.常用的值类型有:(struct) 整型家族:int,byte,char,short,long等等一系列 浮点家族:float, ...

  7. php提取xml配置参数

    demo1.php <?php class AddressManager{ private $addresses = array("ip地址1","ip地址2&qu ...

  8. 手牵手,从零学习Vue源码 系列二(变化侦测篇)

    系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...

  9. MacOS下smartSVN使用教程

    摘要: 本文介绍smartSVN使用教程,以及如何切换smartSVN的用户账号,如何显示远程服务器内容. 1.下载安装smartSVN 我共享一个我的百度云链接 链接:https://pan.bai ...

  10. python爬虫基础要学什么,有哪些适合新手的书籍与教程?

    一,爬虫基础: 首先我们应该了解爬虫是个什么东西,而不是直接去学习带有代码的内容,新手小白应该花一个小时去了解爬虫是什么,再去学习带有代码的知识,这样所带来的收获是一定比你直接去学习代码内容要多很多很 ...