设计模式之开闭原则

开闭原则

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

1.开闭原则概述

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

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

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

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

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

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

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

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

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

java 复制代码
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("错误");
        }
    }
}

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

java 复制代码
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;
    }
}

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

java 复制代码
// 当需要添加新的运算如乘法时
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.定义数据访问层接口

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

2.接口实现类

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

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

3.主程序使用DataAccess接口

java 复制代码
public class Application {
    private DataAccess dataAccess;
    
    public void setDataAccess(DataAccess da) {
        this.dataAccess = da;
    }
    
    public void performDatabaseOperation() {
        dataAccess.connect();
        dataAccess.executeQuery("...");
    }
}
相关推荐
2301_7717172116 分钟前
解决mysql报错:1406, Data too long for column
android·数据库·mysql
小江的记录本37 分钟前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
dvjr cloi42 分钟前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
dFObBIMmai1 小时前
MySQL主从同步中大事务导致的延迟_如何拆分大事务优化同步
jvm·数据库·python
szccyw01 小时前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
czlczl200209252 小时前
利用“延迟关联”优化 MySQL 巨量数据的深分页查询
数据库·mysql
ACP广源盛139246256732 小时前
IX8024与科学大模型的碰撞@ACP#筑牢科研 AI 算力高速枢纽分享
运维·服务器·网络·数据库·人工智能·嵌入式硬件·电脑
Elastic 中国社区官方博客2 小时前
ES|QL METRICS_INFO 和 TS_INFO:为你的时间序列数据建立目录
大数据·数据库·elasticsearch·搜索引擎·信息可视化·全文检索
灰子学技术2 小时前
Envoy 使用的设计模式技术文档
设计模式
俺不要写代码3 小时前
数据库:函数
数据库·mysql