资讯专栏INFORMATION COLUMN

设计模式之适配器模式

booster / 804人阅读

摘要:定义和类型定义将一个类的接口转换成客户期望的另一个接口,适配器模式让那些不兼容的类可以一起工作。类型结构型类适配器模式类适配器模式使用继承的方式去实现接口适配。它是适配器模式的核心。

0x01.定义和类型

定义:将一个类的接口转换成客户期望的另一个接口,适配器模式让那些不兼容的类可以一起工作。

类型:结构型

a.类适配器模式

类适配器模式:使用继承的方式去实现接口适配。

UML:

Java实现

/**
 * 客户需要的接口
 */
public interface Target {
    void request();
}

/**
 * 被适配的类
 */
public class Adaptee {
    public void adapteeRequest () {
        System.out.println("被适配者的方法");
    }
}

/**
 * 适配器,继承了被适配的类,并且实现了Target定义的接口
 */
public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        //todo...
        System.out.println("适配后----");
        super.adapteeRequest();
        //todo...
    }
}

测试与应用

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        adaptee.adapteeRequest();

        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}

输出结果

被适配者的方法
适配后----
被适配者的方法
b.对象适配器模式

对象适配器模式:使用组合的方式去实现接口适配

UML

Java实现

/**
 * 客户端应用放使用的接口
 */
public interface Target {
    void request();
}

/**
 * 被适配的类
 */
public class Adaptee {
    public void adapteeRequest () {
        System.out.println("被适配者的方法");
    }
}

/**
 * 适配器模式
 */
public class Adapter implements Target {

    /**
     * 组合了被适配的类,这里可以通过set方式注入
     */
    private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        //todo...
        System.out.println("适配后----");
        adaptee.adapteeRequest();
        //todo...
    }
}

应用与测试类

/**
 * 应用测试类
 */
public class Test {

    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        adaptee.adapteeRequest();

        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}

输入结果

被适配者的方法
适配后----
被适配者的方法
c.角色介绍

从上面两种情况可以看出,适配器模式一共有三个角色

Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。

Adapter(适配器类):它可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。它是适配器模式的核心。

Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。

0x02.适用场景

已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)

创建一个可以重复使用的类,用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作

适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案。

0x03.优点

能提高类的透明性和复用,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,现有的类复用但不需要改变,而且提高了适配者的复用性,同一适配者类可以在多个不同的系统中复用。

目标类和适配器类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构,提高程序扩展性。

灵活性和扩展性都非常好,通过使用配置文件,可以很方便的更换适配器,也可以在不修改原有代码的基础上,增加新的适配器,符合开闭原则。

0x04.缺点

适配器编写过程需要全面考虑,可能会增加系统的复杂性。

一次最多只能适配一个适配者类,不能同时适配多个适配者。

增加系统代码可读的难度。

0x05. 样例实现
笔记本的插头为三项电,而现有的插座是两项的,需要适配器来进行适配,下面分别进行两种方式的实现。

通用代码

/**
 * 三项插座接口
 * @author Administrator
 *
 */
public interface ThreePlugIf {
    //使用三项电流供电
    void powerWithThree();
}

/**
 * 二项电插座
 */
public class GBTowPlug {
    //使用二项电流供电
    public void powerWithTwo () {
        System.out.println("使用二项电流供电");
    }
}

/**
 * 笔记本类
 */
public class NoteBook {

    private ThreePlugIf plug;

    /**
     * 只接收使用三项电充电
     * @param plug
     */
    public NoteBook (ThreePlugIf plug) {
        this.plug = plug;
    }

    /**
     * 使用插座充电
     */
    public void charge () {
        plug.powerWithThree();
    }
}
a.类适配器的实现

具体Java代码

/**
 * 采用继承方式的插座适配器
 * @author Administrator
 */
public class TwoPlugAdapterExtends extends GBTowPlug implements ThreePlugIf {

    public void powerWithThree() {
        System.out.println("借助继承适配器");
        this.powerWithTwo();
    }
}

测试与应用类

/**
 * 测试与应用类
 */
public class AdapterTest {

    public static void main(String[] args) {
        ThreePlugIf three = new TwoPlugAdapterExtends();
        NoteBook book = new NoteBook(three);
        book.charge();
    }
}

输出结果

借助继承适配器
使用二项电流供电

样例UML类图:

b.对象适配器的实现

具体Java代码

/**
 * 二项插座转三项插座的适配器
 */
public class TwoPlugAdapter implements ThreePlugIf {

    /**
    * 组合
    */
    private GBTowPlug plug;

    public TwoPlugAdapter (GBTowPlug plug) {
        this.plug = plug;
    }

    public void powerWithThree() {
        System.out.println("通过转化");
        plug.powerWithTwo();
    }
}

测试与应用类

/**
 * 测试与应用类
 */
public class AdapterTest {
    public static void main(String[] args) {
        GBTowPlug two = new GBTowPlug();
        ThreePlugIf three = new TwoPlugAdapter(two);
        NoteBook book = new NoteBook(three);
        book.charge();
    }
}

输出结果

对象适配器-通过转化
使用二项电流供电

样例UML类图:

0x06.相关设计模式

适配器模式和外观模式

对现有的类现存系统的封装

外观:定义了新的接口,创建新的接口对现有接口的封装

适配器:复用原有的接口,使两个已有的接口协同工作

两种:适配的力度不同,外观针对的力度更大

0x07.源码中的适配器

JDK: XmlAdapter

Spring AOP: AdvisorAdapter, MethodBeforeAdvice

Spring Data JPA: JpaVendorAdapter

Spring MVC: Handler Adacpter

0x08.源码地址

适配器模式: https://github.com/sigmako/design-pattern/tree/master/adapter

0x09.参考

慕课网设计模式精讲: https://coding.imooc.com/class/270.html

设计模式:适配器模式: https://www.cnblogs.com/songyaqi/p/4805820.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75601.html

相关文章

  • 一天一个设计模式JS实现——配器模式

    摘要:本文参考于设计模式课程设计模式之适配器模式设计模式是一套被反复使用的多数人知晓的经过分类编目的代码设计经验的总结。第一个设计模式是适配器模式。总的来说适配器就是的模式,与修饰模式直接无感使用不同,适配器模式使用对象变为。 本文参考于:设计模式课程设计模式之适配器模式 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被...

    Aceyclee 评论0 收藏0
  • 转换插座配器模式

    摘要:适配器模式之数据格式转换适配器模式不仅可以起到适配接口名的作用,它另外还有一个功能就是能统一不同格式的作用。我们的目的就是在程序中,不要出现适配器模式,但考虑到实际,这也是不可能的,所以尽量将代码设计符合规范是非常必要的。 这个模式应该算是除了单例模式以外最简单的一个模式,没有多余的类,这个模式只有一个职责,就是转换的你接口参数,归一化接口调用函数,同意参数格式。 说人话~其实就是,将...

    MudOnTire 评论0 收藏0
  • JavaScript设计模式配器模式

    摘要:旧接口格式和使用者不兼容,中间加一个适配器转换接口。模式作用使用一个已经存在的对象,但其方法或接口不符合你的要求。 原文博客地址:https://finget.github.io/2018/11/22/adapter/ 适配器模式 适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转换成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作...

    CNZPH 评论0 收藏0
  • 设计模式配器模式

    摘要:适配器模式将一个类的接口转换为客户期望的另一个接口。取桔子包装准备用途苹果盒代替把苹果盒适配成桔子包装盒桔子包装适配器适配器模式结构图用法继承,同时组合对象引入成员变量使和产生关联。 适配器模式:将一个类的接口转换为客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。 场景:水果店卖有橘子和苹果,橘子用橘子包装盒,苹果用苹果包装盒,顾客A来买橘子,但是没有橘子包装盒了,则用苹...

    Drummor 评论0 收藏0
  • PHP设计模式配器模式

    摘要:简介适配器模式有时候也称包装样式或者包装将一个类的接口适配成用户所期待的。应用场景如程序数据库有关联等操作,而你需要根据情况换数据库操作时,可以使用适配器模式统一接口,这样代码中除了数据库配置之外,就不需要做而外的更改。 简介 适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起。 UML 角色 Tar...

    netScorpion 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<