当前位置: 首页 > article >正文

重构代码之引入本地扩展

当我们使用外部库或第三方类时,如果需要扩展其功能,但无法直接修改其代码(例如因为该类是第三方提供的,或直接修改违反了封装性原则),可以通过引入本地扩展类来为该类添加新的功能。本地扩展类提供了一种安全、灵活且可维护的方式来扩展不可更改的类。

一、适用场景

  1. 无法修改第三方类:第三方库的代码不可修改,但需要扩展其功能。
  2. 避免污染代码库:直接修改外部类可能会在未来升级或维护时引发冲突。
  3. 提升可读性:在不破坏现有结构的情况下,为外部类添加自定义的行为或方法。
  4. 集中管理扩展逻辑:通过一个扩展类集中实现与该外部类相关的逻辑,避免分散实现导致的维护复杂性。

二、实现方式

有两种主要方法实现引入本地扩展:

  1. 继承(Subclassing)

    • 创建一个继承自目标类的子类,并在其中添加需要的功能。
    • 适用于目标类未被声明为 sealed 或者 final 的情况。
  2. 包装(Wrapper/Decorator)

    • 创建一个包装类,该类封装目标类,并通过组合方式扩展其功能。
    • 更加灵活,可用于无法继承的类(如 sealed 类)。

三、示例

示例 1:通过继承扩展

假设有一个第三方类 DateRange,没有提供方法检查某一日期是否在范围内:

public class DateRange
{
    public DateTime StartDate { get; }
    public DateTime EndDate { get; }

    public DateRange(DateTime startDate, DateTime endDate)
    {
        StartDate = startDate;
        EndDate = endDate;
    }
}

通过继承扩展功能:

public class ExtendedDateRange : DateRange
{
    public ExtendedDateRange(DateTime startDate, DateTime endDate)
        : base(startDate, endDate)
    {
    }

    public bool IsDateInRange(DateTime date)
    {
        return date >= StartDate && date <= EndDate;
    }
}

// 使用
var dateRange = new ExtendedDateRange(DateTime.Now.AddDays(-5), DateTime.Now.AddDays(5));
Console.WriteLine(dateRange.IsDateInRange(DateTime.Now)); // 输出 True
示例 2:通过包装扩展

假设 DateRange 是一个不可继承的类(标记为 sealed):

public sealed class DateRange
{
    public DateTime StartDate { get; }
    public DateTime EndDate { get; }

    public DateRange(DateTime startDate, DateTime endDate)
    {
        StartDate = startDate;
        EndDate = endDate;
    }
}

通过包装实现扩展功能:

public class DateRangeExtension
{
    private readonly DateRange _dateRange;

    public DateRangeExtension(DateRange dateRange)
    {
        _dateRange = dateRange;
    }

    public bool IsDateInRange(DateTime date)
    {
        return date >= _dateRange.StartDate && date <= _dateRange.EndDate;
    }
}

// 使用
var dateRange = new DateRange(DateTime.Now.AddDays(-5), DateTime.Now.AddDays(5));
var extendedDateRange = new DateRangeExtension(dateRange);
Console.WriteLine(extendedDateRange.IsDateInRange(DateTime.Now)); // 输出 True

三、优缺点

优点

  1. 避免直接修改第三方类,增强安全性。
  2. 提高代码的复用性和可读性。
  3. 灵活选择继承或包装,适应不同的技术限制。

缺点

  1. 增加了额外的类,可能引入一些代码复杂性。
  2. 使用包装时,需要额外编写代码来转发原始类的方法调用。

四、注意事项

  1. 评估是否有必要引入扩展类:有时简单的扩展可以通过扩展方法(Extension Methods)实现,无需创建新的类。
  2. 命名清晰:本地扩展类的命名应清楚传达其用途,例如 ExtendedHelper 后缀。
  3. 封装细节:扩展类应专注于添加功能,避免重新实现现有类的逻辑。

通过引入本地扩展可以在不破坏外部类的情况下灵活扩展功能,同时保持代码的清晰和可维护性。


http://www.kler.cn/a/405423.html

相关文章:

  • 【Stable Diffusion】 超大尺寸绘制、分区控制,详解Tiled Diffusion VAE插件功能
  • TabNet 模型示例
  • 算法.图论-习题全集(Updating)
  • 【pytorch-04】:线性回归案例(手动构建)
  • STM32H7开发笔记(2)——H7外设之多路定时器中断
  • CSS中Flex布局应用实践总结
  • 【IOS】编译缓存错误Library/Caches/com.apple.mobile.installd.staging
  • 直流电表精准计量,为光伏产业续航
  • 2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)
  • 分治法的魅力:高效解决复杂问题的利器
  • 什么是axios?怎么使用axios封装Ajax?
  • 第1章 初识SpringMVC
  • 【滑动窗口】至少有k个重复字符的最长子串
  • 系统思考—跳出症状看全局
  • 【linux013】文件操作命令篇 - less 命令
  • python使用 `importlib.resources` 管理资源文件
  • FPC柔性线路板与智能生活的融合
  • 【电路笔记 TMS320F28335DSP】时钟+看门狗+相关寄存器(功能模块使能、时钟频率配置、看门狗配置)
  • Spark RDD(弹性分布式数据集)的深度理解
  • 向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)
  • 基于深度学习的机动车驾驶重量识别预测研究思路,引入注意力,以及实验验证与性能评估
  • STM32 BootLoader 刷新项目 (十一) Flash写操作-命令0x57
  • Unity开发抖音小游戏使用长音频和短音频
  • Docker Compose安装部署PostgreSQL数据库
  • 工商银行湖仓智一体创新应用实践
  • 数据结构——栈、队列