把书读薄 | 《设计模式之美》设计模式与范式(结构型-适配器模式)(下)

简介: 本文对应设计模式与范式:结构型(51),适配器模式 (Adapter Pattern)。 了解定义,适用场景、类适配器和对象适配器就差不多了~Tips:二手知识加工难免有所纰漏,感兴趣有时间的可自行查阅原文,谢谢。

0x3、对象适配器


还是上面的例子,改用对象适配器写一波,直接新建一个对象适配器类:


public class ObjectAdapter implements Chinese {
    private English english;
    public ObjectAdapter(English english) {
        this.english = english;
    }
    @Override
    public void speakChinese(String talk) {
        english.speakEnglish(talk);
        System.out.println("假装请求了翻译接口,输出翻译结果:【中文】玛卡巴卡");
    }
}
// 测试用例
public static void main(String[] args) {
    Chinese translator = new ObjectAdapter(new English());
    translator.speakChinese("Ma ka ba ka");
}


运行输出结果同上,从代码不难看出两者的区别:


对象适配器支持传入被适配器对象,可以灵活地做到多种被适配接口的适配,而类适配器直接继承,无法动态修改(Java不支持多继承),所以对象适配器平时用得多一些。


UML类图如下:


网络异常,图片无法展示
|


角色如下:


  • Target (目标接口) → 客户所期待的接口,可以是具体或抽象的类,也可以是接口;


  • Adaptee (需要适配的类) → 又称适配者类;


  • Adapter (适配器) → 包装一个需要适配的对象,把原接口转换成目标接口;


0x4、单接口适配器模式


又称 缺省适配器模式,就是目标接口有多个方法,用一个抽象类实现接口,重写每个方法提供默认实现(空方法),子类按需重写父类方法。


比如上面的例子,中文也有很多类型啊,普通话、广州话、潮汕话、客家话、上海话等,但现在只需要转成普通话:


interface ChineseTarget {
    void speakChinese(String talk); // 普通话
    void speakCantonese(String talk);   // 广州话
    void speakChiuchow(String talk);    // 潮汕话
    void speakHakka(String talk);   // 客家话
}
public abstract class BaseAdapter implements ChineseTarget {
    @Override public void speakChinese(String talk) { }
    @Override public void speakCantonese(String talk) { }
    @Override public void speakChiuchow(String talk) { }
    @Override public void speakHakka(String talk) { }
}
public class CantoneseTranslator extends BaseAdapter {
    private English english;
    public CantoneseTranslator(English english) { this.english = english; }
    @Override public void speakCantonese(String talk) {
        english.speakEnglish(talk);
        System.out.println("假装请求了翻译接口,输出翻译结果:【广州话】玛卡巴卡");
    }
}
// 测试用例
public static void main(String[] args) {
    BaseAdapter translator = new CantoneseTranslator(new English());
    translator.speakCantonese("Ma ka ba ka");
}


运行输出结果如下:


网络异常,图片无法展示
|


最后说下适配器模式的有优缺点,先是


优点


  • 目标类与适配者类解耦,引用适配器类来重用现有待适配者类,无需修改原有结构;


  • 增加了类的透明性和复用性,将具体业务实现封装在适配器类中,适配者类改动只影响适配器类;


  • 灵活性和扩展性非常好,可以方便地替换适配器类,可将多个不同的适配者类和子类匹配到同一个目标类上;


  • 符合开闭(OCP)原则和里氏替换原则(LSP);


缺点:


  • 过度嵌套会导致接口臃肿,一个目标类功能下先,会影响整条适配链;


  • 目标接口依赖太多适配接口,修改目标接口会导致所有适配接口都要定制修改;


  • Java中,类适配器目标抽象类只能为接口,且适配者类不能为最终类(final,不能继承);


0x4、加餐:四种结构性设计模式对比


这四种模式的代码结构非常相似,笼统地来说,它们都可以称为 Wrapper模式,即通过Wrapper类二次封装原始类。但它们的用意完全不同(解决的问题、应用场景),下面简单地说下区别。


  • 代理模式:不改变原始类接口条件下,为其定义一个代理类,主要目的是控制访问,而非加强,与装饰器模式最大的不同。


  • 桥接模式:解决类继承因广度引起的类爆炸问题,将接口部分与实现部分分离,从而使得它们可以较为容易、相对独立的变化。


  • 装饰器模式:解决类继承因深度引起的类爆炸问题,在不改变原始类接口的情况下,进行功能增强,且支持多个装饰器嵌套使用。


  • 适配器模式:一种事后补救策略,实现不同接口功能间的转换。
相关文章
|
4天前
|
设计模式 存储 缓存
第三篇 结构型设计模式 - 简化复杂系统的结构
第三篇 结构型设计模式 - 简化复杂系统的结构
|
6天前
|
设计模式 Java Go
【设计模式】适配器模式怎么理解?
【设计模式】适配器模式怎么理解?
8 1
|
6天前
|
设计模式 存储 Java
[设计模式Java实现附plantuml源码~结构型]实现对象的复用——享元模式
[设计模式Java实现附plantuml源码~结构型]实现对象的复用——享元模式
|
6天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~结构型]处理多维度变化——桥接模式
[设计模式Java实现附plantuml源码~结构型]处理多维度变化——桥接模式
|
6天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式
[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式
|
6天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~结构型]对象的间接访问——代理模式
[设计模式Java实现附plantuml源码~结构型]对象的间接访问——代理模式
|
6天前
|
设计模式 安全 Java
[设计模式Java实现附plantuml源码~结构型]树形结构的处理——组合模式
[设计模式Java实现附plantuml源码~结构型]树形结构的处理——组合模式
|
6天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~结构型] 扩展系统功能——装饰模式
[设计模式Java实现附plantuml源码~结构型] 扩展系统功能——装饰模式
|
6天前
|
设计模式 JavaScript 前端开发
[设计模式Java实现附plantuml源码~结构型] 提供统一入口——外观模式
[设计模式Java实现附plantuml源码~结构型] 提供统一入口——外观模式
|
6天前
|
设计模式 API
【设计模式】适配器和桥接器模式有什么区别
【设计模式】适配器和桥接器模式有什么区别
10 1