首页 > 编程语言 >深入理解 C# 中的适配器模式:连接不兼容的世界

深入理解 C# 中的适配器模式:连接不兼容的世界

时间:2024-08-30 15:54:56浏览次数:11  
标签:C# 适配 适配器 接口 兼容 IPaymentGateway 模式 public

在软件开发中,我们经常会遇到需要将两个不兼容的接口连接在一起的场景。适配器模式(Adapter Pattern)作为结构型设计模式之一,提供了一种灵活的解决方案,使得不兼容的接口能够协同工作,从而提高系统的可扩展性和复用性。

本文将详细介绍适配器模式的概念、适用场景,并通过一个 C# 示例演示如何在实际项目中应用适配器模式。

一、适配器模式的概念

适配器模式的主要目的是将一个接口转换成客户端期望的另一个接口,使得原本由于接口不兼容而无法一起工作的类可以协同工作。它的结构包括以下几个部分:

  • 目标接口(Target Interface): 定义客户端所期待的接口。
  • 待适配类(Adaptee): 具有不兼容接口的现有类。
  • 适配器类(Adapter): 实现目标接口,并通过包装一个待适配类的实例,将其接口转换为目标接口。
  • 客户端(Client): 使用目标接口与适配器交互。

二、适配器模式的应用场景

适配器模式适用于以下情况:

  1. 遗留代码复用: 当你需要使用一些遗留代码或第三方库,但它们的接口与当前系统不兼容时,适配器模式可以将其转换为可用的接口。
  2. 接口转换: 当系统中存在多个接口且希望通过一个统一接口进行操作时,适配器模式能够提供接口的一致性。
  3. 提高系统灵活性: 通过引入适配器,可以在不修改现有代码的情况下使用新功能或替换实现。

三、C# 中的适配器模式实现

以下是一个在 C# 中实现适配器模式的示例。我们将模拟一个支付系统,其中有不同的支付网关,而我们的客户端需要一个统一的接口来处理所有支付。

using System;

namespace AdapterPattern
{
    // 目标接口:定义统一的支付接口
    public interface IPaymentGateway
    {
        void MakePayment(decimal amount);
    }

    // 待适配类:现有的支付系统1
    public class LegacyPaymentSystemA
    {
        public void ProcessPayment(decimal amount)
        {
            Console.WriteLine($"使用遗留支付系统A处理{amount}元的支付。");
        }
    }

    // 待适配类:现有的支付系统2
    public class LegacyPaymentSystemB
    {
        public void ExecutePayment(decimal amount)
        {
            Console.WriteLine($"使用遗留支付系统B执行{amount}元的支付。");
        }
    }

    // 适配器类:适配LegacyPaymentSystemA
    public class PaymentAdapterA : IPaymentGateway
    {
        private readonly LegacyPaymentSystemA _legacyPaymentSystemA;

        public PaymentAdapterA(LegacyPaymentSystemA legacyPaymentSystemA)
        {
            _legacyPaymentSystemA = legacyPaymentSystemA;
        }

        // 将目标接口的方法转换为待适配类的方法
        public void MakePayment(decimal amount)
        {
            _legacyPaymentSystemA.ProcessPayment(amount);
        }
    }

    // 适配器类:适配LegacyPaymentSystemB
    public class PaymentAdapterB : IPaymentGateway
    {
        private readonly LegacyPaymentSystemB _legacyPaymentSystemB;

        public PaymentAdapterB(LegacyPaymentSystemB legacyPaymentSystemB)
        {
            _legacyPaymentSystemB = legacyPaymentSystemB;
        }

        // 将目标接口的方法转换为待适配类的方法
        public void MakePayment(decimal amount)
        {
            _legacyPaymentSystemB.ExecutePayment(amount);
        }
    }

    // 客户端代码
    class Program
    {
        static void Main(string[] args)
        {
            // 使用适配器来统一操作不同的支付系统
            IPaymentGateway paymentGatewayA = new PaymentAdapterA(new LegacyPaymentSystemA());
            IPaymentGateway paymentGatewayB = new PaymentAdapterB(new LegacyPaymentSystemB());

            // 执行支付
            paymentGatewayA.MakePayment(100.00m);
            paymentGatewayB.MakePayment(200.00m);
        }
    }
}

四、代码解析

  1. 目标接口 IPaymentGateway: 定义了一个统一的支付接口 MakePayment,所有支付系统都需要实现这个接口。
  2. 待适配类 LegacyPaymentSystemA 和 LegacyPaymentSystemB: 这两个类代表了现有的支付系统,它们的接口与目标接口 IPaymentGateway 不兼容。
  3. 适配器类 PaymentAdapterA 和 PaymentAdapterB: 这些适配器类实现了 IPaymentGateway 接口,并将目标接口的方法调用转换为待适配类的方法调用。这样,客户端可以通过
    IPaymentGateway 接口来操作不同的支付系统,而不需要了解它们的具体实现。
  4. 客户端代码: 在 Main 方法中,客户端通过 IPaymentGateway 接口与支付系统交互,无需关心支付系统的具体实现细节。

五、适配器模式的类型

适配器模式有两种主要类型:

  1. 类适配器(Class Adapter): 通过多重继承来适配接口。由于 C# 不支持多重继承,因此通常使用接口适配器。
  2. 对象适配器(Object Adapter): 通过组合(即将一个对象作为适配器类的成员变量)来适配接口。这也是本文中所使用的方式。

六、适配器模式的优缺点

优点:

  • 提高代码复用性: 可以将现有类与新接口集成,避免重复开发。
  • 增强系统灵活性: 客户端代码与具体实现解耦,可以轻松替换底层实现。

缺点:

  • 增加系统复杂性: 需要额外的适配器类来连接接口,可能导致代码结构复杂化。
  • 性能开销: 适配器模式增加了额外的调用层次,可能会引入一些性能开销。

七、总结

适配器模式是一个非常实用的设计模式,尤其在面对不兼容接口的整合时。通过适配器模式,开发者可以在不修改现有代码的情况下,使得不同的接口能够协同工作,从而提升系统的扩展性和维护性。

在本文中,我们通过一个 C# 的实际示例展示了如何使用适配器模式来整合不同的支付系统。理解和应用适配器模式,可以帮助我们在软件开发中更好地应对接口不兼容的问题。

标签:C#,适配,适配器,接口,兼容,IPaymentGateway,模式,public
From: https://blog.csdn.net/qq_40998698/article/details/141720286

相关文章

  • JavaScript 的模板字符串
    字符串插值JavaScript中使用反引号`包裹的字符串叫模板字符串(templateliterals)。人们常用它拼接变量和字符串,即所谓的字符串插值(stringinterpolation)。在使用字符串插值时,使用${}包裹变量或表达式,它是变量的占位符。多行文本模板字符串支持多行文本(multi-linestr......
  • 通过图形界面安装oracle 19c client
    服务器配置检查1)检查/tmp目录,至少需要400MB空间2)检查swap分区 256MB:3timesthesizeofRAM Between256MBand512MB:2timesthesizeofRAM Between512MBand2GB:1.5timesthesizeofRAM Between2GBand16GB:EqualtothesizeofRAM Morethan......
  • 使用Opatch命令报错:Java (1.7) could not be located. OPatch cannot proceed!
    问题描述[oracle@servernamedb]$OPatch/opatchversionOPatch/opatch:line839:[:toomanyargumentsOPatch/opatch:line839:[:toomanyargumentsJava(1.7)couldnotbelocated.OPatchcannotproceed!OPatchreturnswitherrorcode=1解决方案删除OPatch目录......
  • 基于协同过滤算法的电影推荐系统的设计与实现(论文+源码)_kaic
    摘 要现在观看电影已逐渐成为人们日常生活中最常见的一种娱乐方式,人们通常会在周末或在休息、吃饭时间不由自主地在各种视频软件中搜索当前火热的影视节目。但是现在的视频软件电影推荐功能不够完善,所以需要开发出一套系统来使用户只需要简单操作就能找到喜爱的影片。针对这......
  • C#学习笔记本--第三篇(排序算法之归并排序)
    一、基本原理://归并=递归+合并//数组分左右 //左右元素相比较//满足条件放入新数组//一侧用完放对面//递归不停分分完在排序//排序结束往上走边走边合并//走到头顶出结果//归并排序分为两部分//1.基本排序规则//2.递归平分数组//递归平分数组://不停地分割......
  • C++ 快速输入的优化与缓冲区管理(竞赛必用)
    在编程竞赛和性能敏感的场景中,数据输入的效率往往直接影响到程序的运行速度。为了优化输入操作,我们可以通过手动设定缓冲区的方式来提升输入的速度。本文将详细介绍两种不同的快速输入方案:手动设定缓冲区大小的方案与系统默认缓冲区大小的方案,并结合二进制位数与可表示数据范围......
  • Fibonacci 第 n 项
    //Fibonacci第n项.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*https://loj.ac/p/10220题目描述大家都知道Fibonacci数列吧,f_1=1,f_2=1,f_3=2,f_4=3,~~~,f_n=f_{n-1}+f_{n-2}。现在问题很简单,输入n和m,求f_nmodm。输入格式输入n,m。......
  • 【CSP】坐标变换2(问题拆解,快速输入,知识补充)
    1.题目背景与任务分析题目背景本题要求对二维平面上的点进行指定角度的旋转,并输出旋转后的坐标,要求精确到小数点后六位。这类题目广泛用于考察选手对数学计算、坐标变换以及编程语言中浮点数处理的能力。任务明确输入:多个坐标点及旋转角度。输出:旋转后的新坐标,精确到小数......
  • Vue Cli
    vueCli是基于vue.js进行快速开发的完整系统vue脚手架使用语法:vueinit<模板名称><项目名称>vueinitwebpackvue-spa2安装完成就有项目目录,如下:cdvue-spa2npminstall运行npmrundevbuild构建脚本目录,放置各种配置文件build.js生成环境的构建代码check-versi......
  • Java Script网页设计案例04A6PZbSPCHdMhmS
    1.JavaScript网页设计案例下面我将提供一个简单的JavaScript网页设计案例,该案例将实现一个动态的待办事项列表(TodoList)。用户可以在页面上添加新的待办事项,标记它们为已完成,以及删除它们。这个案例将使用HTML来构建页面结构,CSS来美化页面,以及JavaScript来添加动态功能。1.1HT......