适配器模式

作者:清泓y

链接:https://www.zhihu.com/question/573785160/answer/3111113516

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


这个适配器模式,正如字面意思,就是要去适配某一件物品。       

假如你正在开发一款股票市场监测程序, 它会从不同来源下载 XML 格式的股票数据,

 然后向用户呈现出美观的图表。

开发过程中, 你决定在程序中整合一个第三方智能分析函数库。 

但是遇到了一个问题, 那就是分析函数库只兼容 JSON 格式的数据。

image.png


你可以修改程序库来支持 XML。但是,这可能需要修改部分依赖该程序库的现有代码。

甚至还有更糟糕的情况,你可能根本没有程序库的源代码,从而无法对其进行修改。



解决方案

你可以创建一个适配器。 这是一个特殊的对象, 能够转换对象接口, 使其能与其他对象进行交互。

适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至察觉不到适配器的存在。 

例如, 你可以使用一个将所有数据转换为英制单位 (如英尺和英里) 的适配器封装运行于米和千米单位制中的对象。

适配器不仅可以转换不同格式的数据, 其还有助于采用不同接口的对象之间的合作。 它的运作方式如下:

  1. 适配器实现与其中一个现有对象兼容的接口。

  2. 现有对象可以使用该接口安全地调用适配器方法。

  3. 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象。

有时你甚至可以创建一个双向适配器来实现双向转换调用。


image.png

现实的举例


image.png


如果你是第一次从美国到欧洲旅行,那么在给笔记本充电时可能会大吃一惊。不同国家的电源插头和插座标准不同。

美国插头和德国插座不匹配。

同时提供美国标准插座和欧洲标准插头的电源适配器可以解决你的难题。

实现时使用了构成原则:适配器实现了其中一个对象的接口,

并对另一个对象进行封装。

所有流行的编程语言都可以实现适配器。

image.png




适用场景

  1. 适配器模式允许你创建一个中间层类,其可作为代码与遗留类、

    第三方类或提供怪异接口的类之间的转换器。

2.如果您需要复用这样一些类,他们处于同一个继承体系,并且他们又有了额外的一些共同的方法,

   但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性。

3.当你希望使用某个类,但是其接口与其他代码不兼容时,可以使用适配器类

4. 在一个大项目中,有时候会涉及兼容旧子类,统一接口的场景,这时候可能会用到适配器模式。

实现方式

  1. 确保至少有两个类的接口不兼容:

  • 一个无法修改 (通常是第三方、 遗留系统或者存在众多已有依赖的类) 的功能性服务类。

  • 一个或多个将受益于使用服务类的客户端类。

  • 声明客户端接口, 描述客户端如何与服务交互。

  • 创建遵循客户端接口的适配器类。 所有方法暂时都为空。

  • 在适配器类中添加一个成员变量用于保存对于服务对象的引用。

    通常情况下会通过构造函数对该成员变量进行初始化, 但有时在调用其方法时将该变量传递给适配器会更方便。

  • 依次实现适配器类客户端接口的所有方法。

    适配器会将实际工作委派给服务对象, 自身只负责接口或数据格式的转换。

  • 客户端必须通过客户端接口使用适配器。

    这样一来, 你就可以在不影响客户端代码的情况下修改或扩展适配器。

  • 适配器模式优缺点

    优点:

    • 单一职责原则你可以将接口或数据转换代码从程序主要业务逻辑中分离。

    • 开闭原则。 只要客户端代码通过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。

    缺点:

    代码整体复杂度增加,因为你需要新增一系列接口和类。有时直接更改服务类使其与其他代码兼容会更简单。



演示代码:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 适配器模式_安卓苹果
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("适配器设计模式!");
            IPhoneCharge phoneCharge = new PhoneChargeAdapter();
            phoneCharge.PhoneCharge();
        }
    }

    /// <summary>
    /// 安卓充电接口 
    /// </summary>
    public class AndroidChargeAdapte
    {
        public void AndroidCharge()
        {
            Console.WriteLine("安卓充电线充电!");
        }
    }
    /// <summary>
    /// 客户期待的充电接口 相当于我们类图中的Target
    /// </summary>
    public interface IPhoneCharge
    {
        void PhoneCharge();
    }

    /// <summary>
    /// 将已有的安卓充电接口转换成苹果接口
    /// </summary>
    public class PhoneChargeAdapter : IPhoneCharge
    {
        //在adapter中封装了一个adapte对象,这个对象才是实现功能的对象;
        private AndroidChargeAdapte androidChargeAdapte = new AndroidChargeAdapte();
        public void PhoneCharge()
        {
            androidChargeAdapte.AndroidCharge();
        }
    }


}


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2023-11-30 14:17:30 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864