设计模式 -- 七大原则(五)-- 开闭原则

news2024/11/14 12:17:32

1 基本介绍

  1. 开闭原则(Open Closed Principle,简称OCP)是编程中最基础、最重要的设计原则

  2. 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。

  3. 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

  4. 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

2 实例

2.1 问题程序

public class Ocp {
    public static void main(String[] args) {
        // 使用看看存在的问题
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle()); 
        graphicEditor.drawShape(new Circle()); 
        graphicEditor.drawShape(new Triangle());
    }
}

// 这是一个用于绘图的类 [使用方]
class GraphicEditor {
    // 接收 Shape 对象,然后根据 type,来绘制不同的图形
	public void drawShape(Shape s) {
        if (s.m_type == 1) drawRectangle(s);
        else if (s.m_type == 2) drawCircle(s);
        else if (s.m_type == 3) drawTriangle(s);
    }
    // 绘制矩形
    public void drawRectangle(Shape r) {
        System.out.println(" 绘制矩形 ");
    }
    // 绘制圆形
    public void drawCircle(Shape r) {
        System.out.println(" 绘制圆形 ");
    }
	// 绘制三角形
    public void drawTriangle(Shape r) {
        System.out.println(" 绘制三角形 ");
	}
}


// Shape 类,基类
class Shape {
	int m_type;
}

class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }
}
class Circle extends Shape {
    Circle() {
   		super.m_type = 2;
    }
}
// 新增画三角形
class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }
}

2.2 改进的思路

        把创建 Shape 类做成抽象类,并提供一个抽象的 draw 方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承 Shape,并实现 draw 方法即可,使用方的代码就不需要修改 -> 满足了开闭原则。

public class Ocp {
    public static void main(String[] args) {
    // 使用看看存在的问题
    	GraphicEditor graphicEditor = new GraphicEditor(); 
        graphicEditor.drawShape(new Rectangle()); 
        graphicEditor.drawShape(new Circle()); 
        graphicEditor.drawShape(new Triangle()); 
        graphicEditor.drawShape(new OtherGraphic());
	}
}


// 这是一个用于绘图的类 [使用方] 
class GraphicEditor {
    // 接收 Shape 对象,调用 draw 方法
    public void drawShape(Shape s) {
        s.draw();
    }
}

// Shape 类,基类
abstract class Shape {
    int m_type;
	public abstract void draw();// 抽象方法
}


class Rectangle extends Shape { 
    Rectangle() {
    	super.m_type = 1;
    }
    @Override
    public void draw() {
        System.out.println(" 绘制矩形 ");
    }
}


class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }
    @Override
    public void draw() {
        System.out.println(" 绘制圆形 ");
    }
}

// 新增画三角形
class Triangle extends Shape {
    Triangle() {
    	super.m_type = 3;
    }
    @Override
    public void draw() {
        System.out.println(" 绘制三角形 ");
    }
}

// 新增一个图形
class OtherGraphic extends Shape {
    OtherGraphic() {
        super.m_type = 4;
    }
    @Override
    public void draw() {
        System.out.println(" 绘制其它图形 ");
    }
}                   

3 注意事项

3.1 无法做到完全封闭

  • 预测所有变化困难:软件需求总是在不断变化,很难预测所有可能的变化并对其进行封闭,因此需要根据实际情况灵活应用这一原则。
  • 修改与扩展平衡:尽管开闭原则倡导对修改封闭,但在实际开发中,人们很难做到100%的封闭。因此,需要在不修改已有稳定代码的前提下,通过扩展来实现新功能。

3.2 良好的抽象是基础

  • 创建适当的抽象代价高:创建适当的抽象需要时间和精力,这些抽象也增加了软件设计的复杂性。因此,需要对频繁变化的部分进行抽象,拒绝不成熟的抽象。
  • 持续改进抽象:良好的抽象是实现开闭原则的基础,需要不断改进和优化抽象以适应变化。

3.3 注意扩展方式

  • 接口与抽象类:通过定义清晰的接口或抽象类,并将具体实现细节隐藏在这些接口或抽象类之后,来保护现有代码不被修改。
  • 多态和继承:利用多态和继承创建具有共同特征的子类,并通过重写父类的方法来改变行为,增加系统的灵活性和可扩展性。

3.4 注意封装变化

  • 识别变化点:封装那些可能会变化的部分,通过多态和继承等OO技术实现易于扩展的结构。
  • 提供扩展点:通过插件、配置文件等方式允许功能的扩展,而无需改动已有的代码。

4 总结

        开闭原则(OCP)是面向对象设计中的一个核心原则,它引导着软件实体如类、模块和函数应该在不修改现有代码的情况下进行扩展。其中核心思想就是对扩展开放,对修改关闭。开闭原则是提高软件系统可维护性和灵活性的重要手段。在实际应用中,应充分考虑需求的变动性,合理使用抽象和设计模式来封装变化,从而有效实现开闭原则。同时,也要注意设计的复杂度和性能影响,以便在保持系统稳定的同时,兼顾开发效率和运行效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2069557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

伯努利朴素贝叶斯解析:面向初学者的带代码示例的视觉指南

通过二进制简单性释放预测能力,欢迎来到雲闪世界。 添加图片注释,不超过 140 字(可选) 与虚拟分类器的基线方法或基于相似性的 KNN 推理不同,朴素贝叶斯利用了概率论。它结合了每个“线索”(或特征&#xf…

宿舍管理系统设计与分析

第一章 管理信息系统概述 在人类进入21世纪之际,随着社会的组织化程度以及企业生产的社会化程度越来越高,信息作为一种资源已经和材料、能源并称为现代社会化发展的三大支柱之一。管理信息系统是融科学、信息科学、系统工程以及现代通讯技术、计算机技术…

阿里HPN-大型语言模型训练的数据中心网络架构

阿里巴巴HPN:用于大型语言模型训练的数据中心网络 摘要 本文介绍了阿里云用于大型语言模型(LLM)训练的数据中心网络HPN。由于LLM和一般云计算之间的差异(例如,在流量模式和容错性方面),传统的数据中心网络不太适合LLM训练。这就要求我们专门为LLM培训设…

【NetTopologySuite类库】多边形的五种包围盒(AABB、OBB、包围圆、八边形、凸包)

示例 用的是NetTopologySuite1.5.3版本。 var r new WKTReader(); var wkt "polygon((0 0,0 0.5,1 2,5 0,4 -2,3 -1, 0 0))"; var rawGeo r.Read(wkt); var b1 rawGeo.Envelope;//AABB var b2 new MinimumBoundingCircle(rawGeo).GetCircle();//包围圆 var b3…

基于GeoToolKit实现三维断面的绘制研究

GeoToolkit默认自带PillarSurfaceData的三维断面绘制要求断棱(有时叫断柱)必须是单调的,否则组件底层就会自动优化,导致断面出现回弯,相当于出现重叠,无法实现最终的效果。因此,本文主要在之前文章的基础上,拓展了GeoToolKit的三维断面显示功能。本文主要基于GeoToolKi…

计算机毕业设计hadoop+spark+hive漫画推荐系统 动漫视频推荐系统 漫画分析可视化大屏 漫画爬虫 漫画推荐系统 漫画爬虫 知识图谱 大数据

流程:1.DrissionPageSelenium自动爬虫工具采集漫画视频、详情、标签等约200万条漫画数据存入mysql数据库; 2.Mapreduce对采集的动漫数据进行数据清洗、拆分数据项等,转为.csv文件上传hadoop的hdfs集群; 3.hive建库建表导入.csv动漫…

能精准捕捉股价波峰波谷的 Findpeaks

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话: 在AI对金融产品进行价值分析中,检测波峰波谷具有至关重要的应用意义。投资者可以直接观察股票价格走势图,通过肉眼识别波峰和波谷的位置。这种方法简单易行,但主观性较强,可能受到投资者个人经验…

【最长公共上升子序列】

题目 解决 for (int i 1; i < n; i)for (int j 1; j < n; j){ f[i][j] f[i - 1][j];if (a[i] b[j]){ f[i][j] max(f[i][j], 1);for (int k 1; k < j; k)if (b[j] > b[k])f[i][j] max(f[i][j], f[i - 1][k] 1);} } 先假设不影响结果&#xff0c;纳入 &…

大语言模型的“智能飞轮”!阿里最新综述全面解析大模型的自进化之路

©PaperWeekly 原创 作者 | 林廷恩 单位 | 阿里通义实验室算法研究员 研究方向 | 自然语言处理 想象一下&#xff0c;一个 AI 不仅能学习&#xff0c;还能自我改进&#xff0c;变得越来越聪明。这不是科幻小说&#xff0c;而是我们正在见证的现实。大语言模型&#xff08;…

pdf有密码,如何实现pdf转换word?

PDF想要转换成其他格式&#xff0c;但是当我们将文件拖到PDF转换器进行转换的时候发现PDF文件带有密码怎么办&#xff1f;今天分享PDF有密码如何转换成word方法。 方法一、 PDF文件有两种密码&#xff0c;打开密码和限制编辑&#xff0c;如果是因为打开密码&#xff0c;建议使…

全套安全帽佩戴检测算法源码与实战应用分享

在许多工业环境中&#xff0c;安全帽是确保工人安全的重要防护装备。为了降低工人受伤的风险&#xff0c;尤其是在建筑工地、矿山、工厂等高危环境下&#xff0c;确保工人正确佩戴安全帽是至关重要的。然而&#xff0c;由于现场管理的复杂性和人员流动性&#xff0c;单靠人工监…

Chrome H265 WebRTC 支持

Chrome从127版本开始支持RTC H265解码&#xff0c;这样服务器就不需要对H265转码了&#xff0c; H5S和USC会自动检测浏览器支持的解码类型并自动判断是否启动转码&#xff0c;这样客户端不用关心摄像机具体是H264还是H265&#xff0c;尽量使用带GPU的客户端&#xff0c;这样服务…

什么是红黑树-面试中常问的数据结构

你有没有想过,为什么你的 Java HashMap 能够如此高效地处理数百万个键值对?或者你的 Linux 系统是如何在眨眼间就能管理成千上万的进程的?这些看似神奇的性能背后,隐藏着一个优雅而强大的数据结构 - 红黑树。 目录 什么是红黑树?红黑树的特性为什么需要红黑树?红黑树的结…

java基础 之 抽象类

文章目录 前言抽象类浅浅的理解下抽象类关键字&#xff1a;abstract抽象类 VS 普通类特点 前言 1、类是一个模板&#xff0c;类被继承后成为父类&#xff0c;继承父类的类称为子类。 2、子类可以对父类的方法进行重写&#xff0c;也可以直接使用父类的方法。 3、类称为继承&…

鸿蒙笔记--WorkerTaskPool

这一节了解一下鸿蒙中的Worker和TaskPool,Worker和TaskPool的作用是为应用程序提供一个多线程的运行环境&#xff0c;用于处理耗时的计算任务或其他密集型任务。可以有效地避免这些任务阻塞主线程&#xff0c;从而最大化系统的利用率&#xff0c;降低整体资源消耗&#xff0c;并…

python动画:manim中的颜色【ManimColor】的使用方法

一&#xff0c;什么是彩色(颜色) Color是视觉艺术不可或缺的一部分&#xff0c;但我们怎么知道它如此重要呢&#xff1f;嗯&#xff0c;一种方法是通过色彩理论的应用。什么是色彩理论&#xff1f;我们将定义色彩理论&#xff0c;然后分解来自绘画、照片和电影的各种色彩理论示…

活动预告 | Global RAG Hack Together Ⅲ-用VS Code AI Tools结合SLM构建RAG应用

点击蓝字 关注我们 编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 九月&#xff0c;Global RAG Hack Together 即将在全球开启&#xff0c;在这场全球 RAG 黑客松中&#xff0c;我们不仅可以学习到生成式 AI 下的 RAG 技术&#xff0c;还可以用我们掌握的 RAG 技术提交参…

python读取calibre的opf文件到表格

opf文件之一&#xff1a; python 将 Calibre Library 里面所有opf文件的title&#xff0c;creator&#xff0c;date&#xff0c;description&#xff0c;language&#xff0c;subject内容写入表格中&#xff0c;其中opf之一如上&#xff0c;表头对应为&#xff1a;标题&#xf…

豆包大模型升级:日均Tokens使用量破5000亿,字节跳动打造即刻体验的《Her》式AI

ChatGPT 发布近两年后&#xff0c;全球掀起了一场大模型竞赛&#xff0c;如今怎么将大模型落地&#xff0c;成为萦绕在每一家 AI 公司的最大命题。 最近有媒体统计&#xff0c;自从 GPT-3.5 上线以来&#xff0c;中国新成立的 AI 公司已经有近 8 万家陷入注销、吊销或停业异常…

【前端】vue数据监测原理

问题展示&#xff1a; 点击按钮之后&#xff0c;vue中的persons数据改变&#xff0c;但是页面显示的内容没变。&#xff08;先点击按钮再打开vue的数据面板可以看见改变&#xff0c;先打开后点击数据面板也不能显示改变。&#xff09; 此时的更新代码&#xff1a; methods:{…