Java设计模式之结构型模式 | 适配器模式

48 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情

觉得对你有益的小伙伴记得点个赞+关注

后续完整内容持续更新中

希望一起交流的欢迎发邮件至javalyhn@163.com

0. 情人节序

今天是情人节,没对象的程序员就来分享经验了。。。。。。。。。。。。

1. 适配器模式定义

将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,适配器模式分为类结构型模式(继承)和对象结构型模式(组合)两种,前者(继承)类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

2. 适配器模式使用场景

  • Tomcat如何将Request流转为标准Request;
    • tomcat.Request接口
    • servlet.Request接口
    • tomcat === CoyoteAdapte === ServletRequest
  • Spring AOP中的AdvisorAdapter是什么:增强的适配器
    • 前置、后置、返回、结束 Advisor(通知方法)
    • 底层真的目标方法
  • Spring MVC中经典的HandlerAdapter是什么;
    • HelloController.hello()
    • HandlerAdapter
    • Servlet.doGet()
  • SpringBoot 中 WebMvcConfigurerAdapter为什么存在又取消
  • 系统扩展了,不符合原有设计的时候才考虑通过适配器模式减少修改代码带来的风险。

3. 适配器模式的实现

我们给定以下字幕翻译的场景

image.png

3.1 类适配演示

Player

/**
 * 1、系统原有接口 player:可以播放电影,并且返回字幕
 */
public interface Player {

    String play();
}

Translator

/**
 * 2、系统原有接口,可以翻译文字内容
 */
public interface Translator {
    String translate(String content);
}

Zh_JPTranslator

/**
 * ZH_JP翻译器
 * ZH_EN翻译器
 * .....
 */
public class Zh_JPTranslator implements Translator{
    @Override
    public String translate(String content) {
        if("你好".equals(content)){
            return "空尼几哇";
        }
        if ("什么".equals(content)){
            return "纳尼";
        }
        return "*******";
    }
}

MoviePlayer

/**
 * 电影播放器
 * 阅读器
 * ....
 */
public class MoviePlayer implements Player {
    @Override
    public String play() {
        System.out.println("正在播放:单身狗是如何度过情人节的.avi");
        String content = "你好";
        System.out.println(content);  //并且打印出字幕
        return content;
    }
}

JPMovieAdapter

/**
 * 1、在原有系统上增加一个适配器。让适配器可以把电影的中文字幕翻译成友人理解的日文字幕
 *
 * 客户调用方法的时候用适配器操作即可。
 *
 *
 */
public class JPMovieAdapter extends Zh_JPTranslator implements Player {

    MoviePlayer player = null;
    public JPMovieAdapter(MoviePlayer player){
        this.player = player;
    }

    @Override
    public String play() {
        String context = player.play();
        String translate = translate(context);
        System.out.println("翻译后的内容是:" + translate);
        return translate;
    }
}

MainTest

/**
 *
 * 适配器
 * 1、系统原有两个已存在接口 player、translate没有任何关系
 *
 * 需求,现在一个小....日本友人。看电影字幕是中文的不习惯。
 *
 * 2、我们在不改变原有系统的基础上实现这个功能就需要一个适配器
 *
 *  系统原来存在的所有接口都不能动。扩展一个新的类,来连接两个之前不同的类
 *
 */
public class MainTest {

    public static void main(String[] args) {

        //1、友人想要看电影带日文字幕
        MoviePlayer moviePlayer = new MoviePlayer();
//        moviePlayer.play();

        JPMovieAdapter adapter = new JPMovieAdapter(moviePlayer);
        adapter.play();


    }
}

image.png

3.2 对象适配演示

public class JPMoviePlayerAdapter implements Player {
    
    private   Zh_JPTranslator zh_jpTranslator = new Zh_JPTranslator();
    private Player target;//被适配对象
    public JPMoviePlayerAdapter(Player target){
        this.target = target;
    }

    @Override
    public String play() {

        String play = target.play();
        //转换字幕
        String translate = zh_jpTranslator.translate(play);
        System.out.println("日文:"+translate);
        return play;
    }
}

image.png

4. 适配器模式的优点

  1. 适配器模式可以让两个没有任何联系的类在一起运行,只要适配器这个角色能够搞定他们就可以。
  2. 增加了类的透明性。
  3. 提高了类的复用度。
  4. 灵活性非常好。

5. 注意事项

在详细设计项目阶段尽量不用适配器模式,他不是为了解决还处在开发阶段的问题,而是解决正在服役的项目的问题,主要用在拓展应用中。

希望小伙伴们好好理解以下这个模式