专栏首页程序猿的大杂烩设计模式之适配器模式

设计模式之适配器模式

适配器模式(Adapter)是23种设计模式之一。DP中是这么定义外观模式的:

适配器模式将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以在一起工作。

我们生活中就经常使用到适配器,适配器这个词最早应该是出现在电工学里。有些国家用110V电压,而我国使用的是220V电压,但我们的电器,例如手机、笔记本电脑、平板电脑等,是不能什么电压都能用的,于是我们就需要使用电源适配器,这样一来只要是电,不管多少伏都能适配成需要的电压。而适配器模式就是起到这种作用,将既有的,但是不能够直接使用的,也无法进行改造的,通过适配后,让它能够被使用。

在软件开发中,也就是系统的数据和行为都正确,但是接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。

在GoF的设计模式中,对适配器模式讲了两种类型,类适配器模式和对象适配器模式,由于类适配器模式是通过多重继承对一个接口与另一个接口进行匹配,而Java语言不支持多继承,所以这里只介绍对象适配器模式。

适配器模式(Adapter)结构图:

使用简单的代码来实现这个模式的结构:

Target类:

package org.zero01.target;

/**
 * 客户所期望的接口
 */
public class Target {

    public void request() {
        System.out.println("普通请求!");
    }

}

Adaptee类:

package org.zero01.adapter;

/**
 * 需要适配的类
 */
public class Adaptee {

    public void specificRequest() {
        System.out.println("特殊请求!");
    }

}

Adapter类:

package org.zero01.adapter;

import org.zero01.target.Target;

/**
 * 适配器类
 */
public class Adapter extends Target {

    private Adaptee adaptee = new Adaptee();

    // 把request方法的调用转换成specificRequest方法的调用
    public void request() {
        adaptee.specificRequest();
    }

}

客户端:

package org.zero01.client;

import org.zero01.adapter.Adapter;
import org.zero01.target.Target;

public class Client {

    public static void main(String[] args) {

        Target target=new Adapter();

        // 客户端调用target的request方法即可
        target.request();
    }

}

什么时候适合用适配器模式:

1.想使用一个已经存在的类,但是它的接口,也就是方法与你要求的不同时可以考虑使用适配器模式。也就是说两个类所做的事情相似或相同,但是具有不同的接口时可以使用适配器模式。使用了适配器模式后,类之间就会共享同一个接口,使得客户端代码只需要统一调用同一个接口即可,这样可以使客户端的代码更简单、直接、紧凑。

2.软件开发后期或维护期适合使用适配器模式,因为维护时会由于开发人员的不同,而造成功能类似,但接口不同的情况,此时就适合使用适配器模式。

3.设计一个系统时,如果使用了第三方的组件,而这个组件的接口与我们自己的系统接口不同,但是我们又没有必要为了迎合它而改动自己的接口,这种情况也可以考虑使用适配器模式来解决接口不同的问题。

什么时候不适合用适配器模式:

在设计初期时,就应该统一好接口的定义,尽量不要把接口设计成不同的,以及需要规范好类与方法的命名,所以在这种开发前期的情况下,如果出现接口不同,应该是将不同的接口重构成统一的接口,而不是考虑使用适配器模式。适配器模式应该用在双方都不太容易修改接口的时候再使用适配器模式进行适配。

所以我们开发时应该事先预防接口的不同的问题,这样不匹配的问题就不会发生。在有小的接口不统一而引起问题时,应该及时对接口进行重构,这样问题不至于扩大。只有碰到无法改变原有的设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。适配器模式虽好,但是如果无视它的应用场合而盲目使用,就是本末倒置了。

简单的适配器模式示例:

我这里之前写了一个数码产品充电的系统,但是我现在想要加入一个小灯泡,但是小灯泡与数码产品实现的方法不一样,但是它们同样需要使用电,所以这时候就可以使用适配器了。

结构图如下:

数码产品接口,定义一个充电方法:

package org.zero01.target;

public interface DigitalProducts {

    public void charge();

}

手机、平板以及笔记本电脑都实现了这个接口:

public class Phone implements DigitalProducts{

    public void charge() {

        System.out.println("手机使用4v电压充电");

    }
}

public class IPad implements DigitalProducts{

    public void charge() {

        System.out.println("平板使用6v电压充电");

    }
}

public class MacBook implements DigitalProducts{

    public void charge() {

        System.out.println("笔记本电脑使用14v电压充电");

    }
}

我现在要加入一个小灯泡,但是它们实现的方法不一样:

public class SmallBulb {

    public void electrify() {

        System.out.println("使用1V电压给小灯泡通电");

    }
}

这时候就需要加上一个适配器类了:

/**
 * 适配器类
 */
public class Adapter implements DigitalProducts {

    private SmallBulb smallBulb = new SmallBulb();

    public void charge() {
        smallBulb.electrify();
    }

}

这样在客户端上就可以使用统一的接口了:

package org.zero01.client;

public class Client {

    public static void main(String[] args) {

        DigitalProducts phone = new Phone();
        DigitalProducts ipad = new IPad();
        DigitalProducts macBook = new MacBook();
        DigitalProducts samllBulb = new Adapter();

        phone.charge();
        ipad.charge();
        macBook.charge();
        samllBulb.charge();
    }
}

运行结果:

手机使用4v电压充电
平板使用6v电压充电
笔记本电脑使用14v电压充电
使用1V电压给小灯泡通电

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式之观察者模式

    观察者模式又称为发布-订阅(Publish/Subscribe)模式,是23种设计模式之一。DP中是这么定义观察者模式的:

    端碗吹水
  • 智能合约编程语言-solidity快速入门(下)

    在介绍区块及交易属性之前,我们需要先知道solidity中自带了一些全局变量和函数,这些变量和函数可以认为是solidity提供的API,这些 API 主要表现...

    端碗吹水
  • Java并发编程(8)- 应用限流及其常见算法

    本文仅针对限流做一些简单的说明,那么何为限流呢?顾名思义,限流就是限制流量,就像你宽带包了1个G的流量,用完了就没了。通过限流,我们可以很好地控制系统的qps,...

    端碗吹水
  • [设计模式] 适配器模式 + 外观模式

    顾名思义, ProductV2API是新的API接口, ProductV1API为历史API接口,实现类 HisAPIAdaptee为历史API的实现类,即被适...

    架构探险之道
  • Java设计模式(一)适配器模式

    一天无意中在github上搜索,发现了在Java领域stars排名最多的一个项目:iluwatar/java-design-patterns 里面总结了许多在...

    每天学Java
  • Head First设计模式——适配器和外观模式

    前言:为什么要一次讲解这两个模式,说点骚话:因为比较简单(*^_^*),其实是他们两个有相似和有时候我们容易搞混概念。

    SpringSun
  • [C#1] 11-接口

    接口与继承 CLR规定一个类型只能有一个基类型,这种继承成为单继承; 接口继承是指一个类型继承的是接口中的方法签名,而非方法实现,通常称为实现接口; 接口仅仅是...

    blackheart
  • 适配器模式

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

    xiangzhihong
  • 【大话设计模式】——适配器模式

    将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原来由于接口不兼容而不能一起工作的类可以一起工作。

    程序猿小亮
  • 深入浅出!接口测试其实没有那么高大上

      说起接口测试,网上有很多例子,但是当初做为新手的我来说,看了不不知道他们说的什么,觉得接口测试,好高大上。认为学会了接口测试就能屌丝逆袭,走上人生巅峰,迎娶...

    小老鼠

扫码关注云+社区

领取腾讯云代金券