首页 > 其他分享 >十一:适配器模式:连接世界的桥梁

十一:适配器模式:连接世界的桥梁

时间:2023-04-30 14:04:54浏览次数:32  
标签:十一 String 适配器 桥梁 fileName void audioType public

a. 适配器模式剖析

想象一下你正在进行一场全球旅行,来到了一个陌生的国度。你的手机电量不足,却发现电源插座与你的充电器不兼容。这时,一把万能插头适配器出现在你面前,拯救了你的手机。在软件设计世界里,适配器模式就扮演着这样一个角色,它能够将不兼容的接口进行转换,使得原本无法合作的类能够顺利地协同工作。 适配器模式分为两种:类适配器和对象适配器。类适配器通过继承实现,而对象适配器则通过组合来实现。

b. 编写实例:适配器模式实践

假设我们有一个 MediaPlayer 接口,定义了一个 play() 方法,用于播放各种格式的媒体文件。现在我们有一个 AdvancedMediaPlayer 接口,它支持播放更多格式的媒体文件。我们希望在不修改原有 MediaPlayer 的基础上,使其能够播放 AdvancedMediaPlayer 支持的格式。为此,我们可以引入一个适配器。 首先,定义 MediaPlayer 和 AdvancedMediaPlayer 接口:

public interface MediaPlayer {
    void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer {
    void playVlc(String fileName);
    void playMp4(String fileName);
}

然后,创建实现 AdvancedMediaPlayer 接口的具体类:

public class VlcPlayer implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        System.out.println("Playing vlc file. Name: " + fileName);
    }

    @Override
    public void playMp4(String fileName) {
        // Do nothing
    }
}

public class Mp4Player implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        // Do nothing
    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("Playing mp4 file. Name: " + fileName);
    }
}

接下来,创建适配器类,使得 MediaPlayer 能够使用 AdvancedMediaPlayer:

public class MediaAdapter implements MediaPlayer {
    private AdvancedMediaPlayer advancedMediaPlayer;

    public MediaAdapter(String audioType) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMediaPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMediaPlayer = new Mp4Player();
        }
    }

    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMediaPlayer.playVlc(fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMediaPlayer.playMp4(fileName);
        }
    }
}

最后,创建一个 AudioPlayer 类,它实现了 MediaPlayer 接口,通过 MediaAdapter 类适配 AdvancedMediaPlayer:

public class AudioPlayer implements MediaPlayer {
    private MediaAdapter mediaAdapter;

    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("Playing mp3 file. Name: " + fileName);
        } else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        } else {
            System.out.println("Invalid media. " + audioType + " format not supported.");
        }
    }
}

现在,我们可以通过 AudioPlayer 类来播放 mp3、vlc 和 mp4 格式的文件:

public class AdapterPatternDemo {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();

        audioPlayer.play("mp3", "beyond_the_horizon.mp3");
        audioPlayer.play("mp4", "alone.mp4");
        audioPlayer.play("vlc", "far_far_away.vlc");
        audioPlayer.play("avi", "mind_me.avi");
    }
}

c. 权衡利弊:适配器模式分析

优点:

1、提高了类的复用性。原本无法一起工作的类可以通过适配器进行协同。 2、适配器模式可以实现解耦,提高了代码的可扩展性。 3、可以透明地使用新接口,使得客户端不需要关心适配过程。

缺点:

1、适配器模式可能会导致系统变得复杂,增加了代码的阅读难度。 2、过多地使用适配器可能会使得系统结构变得混乱。

d. 适配器模式在开源框架中的应用

在 Spring 框架中,适配器模式被广泛应用。例如,Spring MVC 中的 HandlerAdapter 就用到了适配器模式。HandlerAdapter 负责将不同类型的处理器(Controller)适配为统一的接口,使得 DispatcherServlet 能够处理各种类型的请求。 以下是 Spring 框架中一个简化版的 HandlerAdapter 示例:

public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

通过实现 HandlerAdapter 接口,可以支持多种类型的处理器。这样,开发者可以方便地扩展和定制自己的处理器类型,而无需修改 DispatcherServlet 的代码。

总结:

适配器模式为解决不同接口之间的兼容性问题提供了优雅的解决方案。通过理解和运用适配器模式,我们可以让原本无法协同工作的类顺利地合作,提高代码的复用性和可扩展性。同时,要注意适配器模式可能带来的系统复杂性和混乱。

标签:十一,String,适配器,桥梁,fileName,void,audioType,public
From: https://blog.51cto.com/u_13616584/6237850

相关文章

  • TNS-12541: TNS: 无监听程序 TNS-12560: TNS: 协议适配器错误
    MicrosoftWindows[版本6.1.7601]版权所有(c)2009MicrosoftCorporation。保留所有权利。C:\Users\Administrator>lsnrctlLSNRCTLfor64-bitWindows:Version11.2.0.1.0-Productionon28-4月-202311:29:22Copyright(c)1991,2010,Oracle.Allrightsreserved......
  • 第十一天打卡
    一、问题描述编写一个计算个人所得税的程序,要求输入收入金额后,能够输出应缴的个人所得税。二、设计思路1.利用结构体记录不同起始征税点、结束点和税率;2.利用函数计算各个阶段的税;3.输出结果。三、四、代码实现 ......
  • 双十一期间,海外企业邮箱如何注册?
    海外企业邮箱价格是外贸公司注册邮箱时要对比的,双十一期间许多企业邮箱会有优惠活动,但是如果你进行对比,对外贸企业来说还是选择ZohoMail企业邮箱划算,最重要的是它的安全级别远高于普通邮箱。海外企业邮箱如何注册呢?1.选择公司邮箱品牌行业里企业邮箱大品牌都是拥有20多年邮箱......
  • Django笔记三十一之全局异常处理
    本文首发于公众号:Hunter后端原文链接:Django笔记三十一之全局异常处理这一篇笔记介绍Django的全局异常处理。当我们在处理一个request请求时,会尽可能的对接口数据的格式,内部调用的函数做一些异常处理,但可能还是会有一些意想不到的漏网之鱼,造成程序的异常导致不能正常运行,......
  • 第三十一章:XPath
    学习要点:1.IE中的XPath2.W3C中的XPath3.XPath跨浏览器兼容XPath是一种节点查找手段,对比之前使用标准DOM去查找XML中的节点方式,大大降低了查找难度,方便开发者使用。但是,DOM3级以前的标准并没有就XPath做出规范;直到DOM3在首次推荐到标准规范行列。大部分浏览器实现了......
  • 十代雅阁对比十一代雅阁
    十代雅阁和十一代雅阁都是本田公司生产的中型轿车,下面是两者的比较:外观设计:十一代雅阁相较于十代雅阁,更加时尚和动感,前脸使用了更大的进气格栅,车身线条更加流畅。内饰设计:十一代雅阁内饰采用更加现代化的设计风格,中控台上配备了更大的触控屏幕,仪表盘也更加智能化。......
  • C++ 学习 第十一天
    今日学习内容:面向对象 面向对象:优势:可以实现数据类型扩展易于理解 呈现形式:类 特性:封装:先将成员绑定为一个整体,再将被绑定成员划分权限,所以在类中,成员和成员直接不遵从代码顺序结构权限:public 公有的:类内可以访问 子类可以访问 类外可以访问privat......
  • 第十一天第二个问题
    问题描述:以点类Point及平面图形类Plane为基类公有派生圆类Circle,main(void)函数完成对其的测试。Point类结构说明:Point类的数据成员包括:①私有数据成员:X坐标x(double型),Y坐标y(double型)。Point类成员函数包括:①有参构造函数Point(double,double)和拷贝构造函数Point(const......
  • 第十一天第一个问题
    问题描述:编写模板函数max5(),他将由一个T类型元素组成的数组作为参数,并返回数组中最大的元素(由于长度固定,因此可以在循环中使用硬编码,而不必通过参数来传递)。在一个程序中使用该函数,将T替换为一个包含5个int值的数组和一个包含5个double值的数组,以测试该函数。解决方法:1.建立一个模......
  • 《c#高级编程》第5章C#5.0中的更改(十一)——字符串插值
    在C#5中,引入了字符串插值(stringinterpolation)语法,它提供了一种简单、直观的方式来将变量的值嵌入到字符串中。在以前的版本中,我们需要使用字符串格式化功能来实现这个目的,例如:intcount=42;stringmessage=string.Format("Theansweris{0}",count);而在C#5中,我......