设计模式之开闭原则

2024-01-07 20:29:53

本片文章在springBoot3,jdk21下测试通过

1.开闭原则概述

1.定义:对扩展开放,对修改关闭

  • 对扩展开放:意味着当系统需要增加新的功能时,可以在不修改现有代码的基础上进行扩展。通过提供抽象层和扩展点来实现新功能,而不是直接修改原有代码
  • 对修改关闭:已经完成并测试过的软件实体(类、模块、函数等)应该尽量避免被修改。一旦软件的一个部分被视为稳定且工作正常,就不应该对其源码做出改动以适应新的需求

2.开闭原则到底解决了什么问题?

  • 应对需求变化:在软件开发过程中,产品经理的需求是难以完全预见的,因此代码需要具备良好的适应性来应对需求变更。开闭原则要求已有的代码结构对新的功能需求能够通过扩展而非修改来实现,从而避免了因直接修改源码带来的风险
  • 降低耦合度:遵循开闭原则的设计倾向于使用抽象类、接口等机制来定义行为,并通过子类或策略等方式进行具体实现。这种方式降低了不同组件之间的耦合度,使得新添加的功能模块不会直接影响到原有系统的核心结构
  • 提高复用性:通过提供稳定的抽象层和明确的扩展点,代码可以更方便地被复用。新增加的功能可以通过增加新的类或者模块来完成,而无需改动现有稳定的部分
  • 减少潜在错误:直接修改已经经过充分测试和验证的代码容易引入新的bug。开闭原则强调不对原有代码进行修改,从而减少了由于修改引发的潜在错误
  • 简化维护:当系统的架构基于开闭原则设计时,维护工作通常会变得更加简单和可控,因为每个功能都是独立且易于替换的,而不是硬编码在整个系统中

3.用代码来列举一个案例

需求:我们有一个计算器类,最初只支持加法操作

大多数程序员都会使用的方式,也就是未遵循开闭原则的代码,如下:

public class JiSuanQi {
    public double init(String operation, double num1, double num2) {
        if ("add".equals(operation)) {
            return num1 + num2;
        } else {
            throw new IllegalArgumentException("错误");
        }
    }
}

更改需求:我们需要添加减法操作

public class JiSuanQi {
    public double init(String operation, double num1, double num2) {
        if ("add".equals(operation)) {
            return num1 + num2;
        } else if ("subtract".equals(operation)) { // 新增代码
            return num1 - num2; // 新增代码
        } else {
            throw new IllegalArgumentException("错误");
        }
    }
}

现在采用遵循开闭原则的例子

public interface Operation {
    double perform(double num1, double num2);
}

public class Addition implements Operation {
    @Override
    public double perform(double num1, double num2) {
        return num1 + num2;
    }
}

public class Subtraction implements Operation {
    @Override
    public double perform(double num1, double num2) {
        return num1 - num2;
    }
}

需求更改:添加一个乘法的方法

// 当需要添加新的运算如乘法时
public class Multiplication implements Operation {
    @Override
    public double perform(double num1, double num2) {
        return num1 * num2;
    }
}

2.开闭原则使用场景

1.支付方式中的使用

代码类似于标题一中遵循开闭原则的例子,此处就省略

2.数据源切换

博主曾经写过一篇关于mybatis动态切换数据源的文章有兴趣的博主自行阅读,连接如下:https://blog.csdn.net/weixin_44702984/article/details/134855131?spm=1001.2014.3001.5502
链接直达

下面的案例只是提供思路,代码可以自行完成
1.定义数据访问层接口

public interface DataAccess {
    // 获取链接
    void connect();
    // 执行SQL
    void executeQuery(String query);
    // 其他通用方法...
}

2.接口实现类

public class MySQLDataAccess implements DataAccess {
    // 实现与MySQL相关的connect, executeQuery等方法...
}

public class OracleDataAccess implements DataAccess {
    // 实现与Oracle相关的connect, executeQuery等方法...
}

3.主程序使用DataAccess接口

public class Application {
    private DataAccess dataAccess;
    
    public void setDataAccess(DataAccess da) {
        this.dataAccess = da;
    }
    
    public void performDatabaseOperation() {
        dataAccess.connect();
        dataAccess.executeQuery("...");
    }
}

文章来源:https://blog.csdn.net/weixin_44702984/article/details/135438215
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。