news 2026/8/16 9:03:58

经典开闭原则实例解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
经典开闭原则实例解析

文章目录

  • 经典开闭原则实例解析?
    • 什么是开闭原则?
    • 开闭原则的核心思想
    • 案例一:计算器程序
      • 不满足开闭原则的情况
      • 满足开闭原则的改进方案
    • 案例二:图形面积计算
      • 不满足开闭原则的情况
      • 满足开闭原则的改进方案
    • 总结
    • 如果你还有其他问题或者需要进一步讨论的地方,请随时告诉我!
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

经典开闭原则实例解析?

各位码农朋友们,闫工又来给大家讲知识点啦!今天我们要聊一个超级重要的设计原则——开闭原则。这个原则听起来有点抽象,但其实它在我们日常编码中随处可见,甚至可以说是一个“隐形”的指导思想。作为一个有追求的码农,掌握开闭原则不仅能让你写出更优雅的代码,还能让你在面试中秒杀对手!所以,今天闫工就带大家一起来深入理解这个经典的设计原则。

什么是开闭原则?

开闭原则(Open/Closed Principle,简称 OCP)是软件工程中的一个核心设计原则,由Bertrand Meyer在1988年提出。它的定义是:

软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭。

换句话说,就是说我们写代码的时候,要让系统能够方便地进行功能扩展,但是尽量避免因为新增功能而修改已有的代码。这样做的好处是什么呢?当然是提高系统的维护性和可扩展性啦!

举个栗子:假设你写了一个计算器程序,支持加减乘除四种运算。后来产品经理突然说还要支持幂运算,这时候你就得想想怎么在不修改原有代码的情况下实现这个新功能。这就是开闭原则的典型应用场景。

开闭原则的核心思想

开闭原则的核心思想是“封闭现有行为,开放未来扩展”。要做到这一点,我们需要遵循以下几个要点:

  1. 抽象层:通过抽象类或接口来定义系统的行为,而不是具体实现。
  2. 依赖注入:让组件之间通过接口而非具体实现进行交互。
  3. 模块化设计:将系统分解成独立的功能模块,每个模块只负责一个职责。

接下来,闫工就带大家通过几个实际案例来理解开闭原则的精髓。

案例一:计算器程序

不满足开闭原则的情况

假设我们有一个简单的计算器程序,支持加减乘除四种运算:

publicclassCalculator{publicintadd(inta,intb){returna+b;}publicintsubtract(inta,intb){returna-b;}publicintmultiply(inta,intb){returna*b;}publicintdivide(inta,intb){if(b==0){thrownewIllegalArgumentException("除数不能为零");}returna/b;}}

这个实现看起来很简单,但如果产品经理突然要求支持幂运算怎么办?我们只能在Calculator类中新增一个方法:

publicintpower(intbase,intexponent){return(int)Math.pow(base,exponent);}

这样确实满足了需求,但问题在于,每次新增功能都需要修改现有的类。这违背了开闭原则中的“对修改关闭”的要求。

满足开闭原则的改进方案

为了遵守开闭原则,我们需要重新设计这个计算器程序。具体来说,可以使用策略模式来实现。

首先,定义一个运算接口:

publicinterfaceOperation{intcompute(inta,intb);}

然后,为每种运算提供具体的实现类:

publicclassAddOperationimplementsOperation{@Overridepublicintcompute(inta,intb){returna+b;}}publicclassSubtractOperationimplementsOperation{@Overridepublicintcompute(inta,intb){returna-b;}}publicclassMultiplyOperationimplementsOperation{@Overridepublicintcompute(inta,intb){returna*b;}}publicclassDivideOperationimplementsOperation{@Overridepublicintcompute(inta,intb){if(b==0){thrownewIllegalArgumentException("除数不能为零");}returna/b;}}

接下来,重新设计Calculator类:

publicclassCalculator{privateOperationoperation;publicvoidsetOperation(Operationoperation){this.operation=operation;}publicintcompute(inta,intb){if(operation==null){thrownewIllegalStateException("运算策略未设置");}returnoperation.compute(a,b);}}

这样,当我们需要新增幂运算功能时,只需要实现一个新的PowerOperation类:

publicclassPowerOperationimplementsOperation{@Overridepublicintcompute(inta,intb){return(int)Math.pow(a,b);}}

然后,在使用计算器时,只需将策略切换到新的PowerOperation即可:

Calculatorcalculator=newCalculator();calculator.setOperation(newAddOperation());System.out.println(calculator.compute(5,3));// 输出: 8calculator.setOperation(newPowerOperation());System.out.println(calculator.compute(2,3));// 输出: 8

通过这种设计,我们实现了“对扩展开放,对修改关闭”的目标。每次新增运算类型时,只需要添加新的实现类,而不需要修改原有的代码。

案例二:图形面积计算

再来看一个常见的例子——图形面积计算。假设我们需要支持多种图形的面积计算,比如圆形、矩形、三角形等。

不满足开闭原则的情况

最简单的实现方式可能是这样的:

publicclassAreaCalculator{publicdoublecalculateArea(Stringtype,double...args){switch(type){case"circle":returnMath.PI*args[0]*args[0];case"rectangle":returnargs[0]*args[1];case"triangle":return0.5*args[0]*args[1];default:thrownewIllegalArgumentException("未知图形类型");}}}

这个实现虽然简单,但问题在于如果需要新增一种图形(比如五边形),就需要修改calculateArea方法的代码。这显然违反了开闭原则。

满足开闭原则的改进方案

同样的,我们可以使用策略模式来解决这个问题。首先定义一个计算面积的接口:

publicinterfaceAreaStrategy{doublecalculate(double...args);}

然后为每种图形提供具体的实现类:

圆形:

publicclassCircleAreaimplementsAreaStrategy{@Overridepublicdoublecalculate(double...args){returnMath.PI*args[0]*args[0];}}

矩形:

publicclassRectangleAreaimplementsAreaStrategy{@Overridepublicdoublecalculate(double...args){returnargs[0]*args[1];}}

三角形:

publicclassTriangleAreaimplementsAreaStrategy{@Overridepublicdoublecalculate(double...args){return0.5*args[0]*args[1];}}

接下来,重新设计AreaCalculator类:

publicclassAreaCalculator{privateAreaStrategystrategy;publicvoidsetStrategy(AreaStrategystrategy){this.strategy=strategy;}publicdoublecalculate(double...args){if(strategy==null){thrownewIllegalStateException("面积计算策略未设置");}returnstrategy.calculate(args);}}

这样,当我们需要新增五边形的面积计算时,只需要实现一个新的PentagonArea类:

publicclassPentagonAreaimplementsAreaStrategy{@Overridepublicdoublecalculate(double...args){// 假设参数是边长和半径return1.72048*Math.pow(args[0],2);// 这是一个简化的计算公式}}

然后在使用时,只需切换策略即可:

AreaCalculatorcalculator=newAreaCalculator();calculator.setStrategy(newCircleArea());System.out.println(calculator.calculate(5));// 计算半径为5的圆面积calculator.setStrategy(newPentagonArea());System.out.println(calculator.calculate(2,3));// 计算五边形面积

通过这种设计,每次新增图形类型时,只需要添加新的策略类,而不需要修改原有的AreaCalculator类。

总结

以上两个案例展示了如何通过策略模式来实现“对扩展开放,对修改关闭”的原则。具体来说:

  1. 定义接口或抽象类:为需要变化的行为定义一个统一的接口。
  2. 具体实现类:将不同的行为实现为具体的类,这些类都实现了相同的接口。
  3. 上下文类:负责维护和切换具体的实现类,并通过这些实现类来处理请求。

这种设计使得系统更加灵活、易于扩展。每次新增功能时,只需添加新的实现类,而不需要修改原有的代码,从而降低了维护成本,提高了系统的可扩展性。

当然,策略模式也有一些缺点:

  1. 增加了类的数量:每种具体的行为都需要一个独立的类。
  2. 需要管理多个类:虽然可以通过工厂或其他机制来管理这些类,但仍然需要额外的工作来确保它们被正确地创建和使用。

不过,在大多数情况下,这种权衡是值得的,因为它能够带来更好的代码结构和更高的扩展性。

如果你还有其他问题或者需要进一步讨论的地方,请随时告诉我!

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 16:06:31

基于STM32F103与MPU6050的立创数字水平仪DIY全流程解析

基于STM32F103与MPU6050的立创数字水平仪DIY全流程解析 最近在工位上捣鼓一些小玩意儿,想着能不能自己做一个既实用又有趣的电子工具。于是,一个数字水平仪的想法就冒出来了。它不仅能测量平面的倾斜角度,还能把数据直观地显示在屏幕上&#…

作者头像 李华
网站建设 2026/7/14 16:06:28

告别环境配置烦恼:WinPython便携开发环境全攻略

告别环境配置烦恼:WinPython便携开发环境全攻略 【免费下载链接】winpython A free Python-distribution for Windows platform, including prebuilt packages for Scientific Python. 项目地址: https://gitcode.com/gh_mirrors/wi/winpython 价值定位&…

作者头像 李华
网站建设 2026/7/14 16:06:30

磁控U位系统:机房资产管理的精准高效解决方案

随着数据中心机房规模扩张、设备密度攀升,U位级资产管理成为运维痛点。传统人工巡检、Excel记录方式效率低下,易出现漏记、错位,且难以通过等保、ISO27001等合规审计,“哪个U位空着、设备在哪、谁动过”成为机房管理者的核心困扰。…

作者头像 李华
网站建设 2026/7/14 16:06:31

3大场景突破抖音内容采集瓶颈:douyin-downloader的高效解决方案

3大场景突破抖音内容采集瓶颈:douyin-downloader的高效解决方案 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容创作与研究领域,高效获取抖音平台的无水印视频一直是内容创…

作者头像 李华
网站建设 2026/8/1 5:15:11

使用IDEA创建java项目和运行保姆级教程

各位刚入门Java的小伙伴,在上一篇教程中,我们已经搞定了JDK的安装和环境配置(没搞定的小伙伴可以先回去补补课,JDK是基础哦)。今天,我们就来实操核心步骤——用IDEA创建第一个Java项目,并且运行经典的Hello World示例! 很多新手第一次打开IDEA,看着满屏的按钮和选项,…

作者头像 李华