贯穿设计模式第二话--开闭职责原则

🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳

从今天开始,将开启一个专栏,【贯穿设计模式】,设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。为了能更好的设计出优雅的代码,为了能更好的提升自己的编程水准,为了能够更好的理解诸多技术的底层源码, 设计模式就是基石,万丈高楼平地起,一砖一瓦皆根基。 ✨✨欢迎订阅本专栏✨✨

🥺 本人不才,如果文章知识点有缺漏、错误的地方 🧐,也欢迎各位人才们评论批评指正!和大家一起学习,一起进步! 👀

❤️ 愿自己还有你在未来的日子,保持学习,保持进步,保持热爱,奔赴山海! ❤️

💬 最后,希望我的这篇文章能对你的有所帮助! 🍊 点赞 👍 收藏 ⭐留言 📝 都是我最大的动力!

📃前言回顾


​ 🔥【贯穿设计模式】第一话·设计模式初介绍和单一职责原则🔥

在第一篇文章中,我们了解设计模式有七大原则,是我们在学习设计模式的基础,我们也学习到了第一个原则:单一职责原则;

我们来回顾下,它的定义:指对一个类来说,应当只有一个引起它变化的原因,否则类应该被拆分,即一个类应该只有一个职责。

并且我们通过学生上课的例子讲解并认识到各个阶段的代码所遇到的问题,也有优缺点,所以在应用单一职责原则时,只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中方法数量足够少,才可以在方法级别上违反单一职责原则。

🌴开闭原则

今天我们要学习的是开闭原则,对扩展开放,对修改关闭。

🌵概述

  • 该原则主要说明的是扩展开放,对修改关闭,即尽量通过扩展软件实体类等来解决需求变化,而不是通过修改已有的代码来完成变化;
  • 实现开闭原则的核心思想就是面向抽象编程,强调的是用抽象构建框架,用实现扩展细节,可以提高软件系统的可复用性及可维护性;
  • 简单理解就是说将功能模块以接口的方式来调用,对功能进行抽象化,并且外部能够实现该功能(接口)。
  • 在一个软件产品在生命周期内,都会发生变化、升级和维护等一系列原因,可能需要对软件原有代码进行修改,也会有可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。既然变化是一个既定的事实,我们就应该在设计的时候尽量适应这些变化,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有代码来实现变化,以此提高项目的稳定性和灵活性;
  • 而举一个生活例子,在现在的互联网公司中,都比较流行一个弹性化工作制,规定每天工作8小时。这个每天工作8小时这个规定是关闭的,但是什么时候来、什么时候走是开放的,早来早走,晚来晚走。因为晚上加班都是时常发生的事情,你有可能凌晨1点才上班,如果第二天要求你9点就得来上班,我相信你估计是起不来的,甚至到公司都会打瞌睡的状态。

🌾特点

开闭原则是编程中最基础最重要的设计原则,如果遵循开闭原则将有以下优点

  • 提高系统的复用性。代码粒度越小,被复用的可能性就越大。开闭原则的设计保证系统是实现了复用的系统。
  • 提高系统的可维护性。一个产品上线后,维护人员的工作不仅仅是对数据进行维护,还可能对程序进行扩展。开闭原则对已有软件模块的要求不能再修改,去扩展一个新类,这就使变化中的软件系统有一定的稳定性和延续性,便于系统的维护。
  • 提高系统的灵活性。我们要知道,需求是无时无刻在变化的,在软件系统面临新的需求时,系统的设计必须是稳定的。开闭原则可以通过扩展已有的软件系统,提供新的行为,能快速应对变化,以满足对软件新的需求,使变化中的软件系统有一定的适应性和灵活性。

🌿问题引出

遥想当初上学时期,甚至在高中的时候,每天的时间都会被大量的习题集,试卷,课后作业占据,除了刷题,就是刷题了,似乎只要刷多了,你就会了。哈哈这里就不细讲当初刷题的苦逼日子了。接下来就以这些习题集等例子来讲解开闭原则吧。

整个习题集的类图如图所示:

1. 习题接口:IExercise:

package com.ygt.principle.ocp;

/**
 * 习题接口,主要有价格和姓名
 */
public interface IExercise {

    Double getPrice();

    String getName();
}

2. 高中习题类实现了习题接口:HighExercise:

package com.ygt.principle.ocp;

/**
 * 高中习题类
 */
public class HighExercise implements IExercise {
    // 习题价格
    private Double price;

    // 习题名字
    private String name;

    // 构造方法
    public HighExercise(Double price, String name) {
        this.price = price;
        this.name = name;
    }

    public Double getPrice() {
        return this.price;
    }

    public String getName() {
        return this.name;
    }
}

3. 习题集店贩卖习题:ExerciseStore:

package com.ygt.principle.ocp;

import java.util.ArrayList;
import java.util.List;

/**
 * 习题店 专门卖习题集的
 */
public class ExerciseStore {


    // 习题店中包含各种习题集
    private List<IExercise> exerciseList = new ArrayList<>();

    // 初始化习题集
    public ExerciseStore() {
        exerciseList.add(new HighExercise(63d, "五年高考三年模拟数学"));
        exerciseList.add(new HighExercise(53d, "五年高考三年模拟语文"));
        exerciseList.add(new HighExercise(43d, "五年高考三年模拟英语"));
    }

    // 展示习题集方法
    public void showExercise() {
        System.out.println("~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~");
        System.out.println("习题名\t\t\t\t\t价格\t\t");
        exerciseList.forEach(e-> System.out.println(e.getName() + "\t\t¥" + e.getPrice() + "元\t\t"));
    }

    // 测试调用习题集
    public static void main(String[] args) {
        ExerciseStore store = new ExerciseStore();
        store.showExercise();
    }
}

4. 演示结果:

~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~
习题名					价格		
五年高考三年模拟数学		¥63.0元		
五年高考三年模拟语文		¥53.0元		
五年高考三年模拟英语		¥43.0

按照上面的写法,我们可以轻松写出习题店售卖习题集的过程,但是习题店每逢寒暑假的时候,为了让广大学子都能做上习题,习题店决定按照8.5折的强大优惠力度促进销售习题,而这时候就需要对现有的售卖习题的过程进行修改。如果按照原先的思路的话,就会直接在HighExercise类上,直接将价格修改。

package com.ygt.principle.ocp;

public class HighExercise implements IExercise {
  
    // ....省略其他代码
   
    public Double getPrice() {
        return this.price * 0.85;
    }
}

下面就一起来探讨下解决方法吧。

☘️解决方案

如果直接修改原先的习题类的话,就会导致不是遵循了开闭原则了,违反了对修改关闭的原则,所以此时不能直接修改HighExercise类或者是IExercise接口了。而是通过扩展一个类来完成该修改价格的需求。

增加一个子类DiscountHighExercise继承HighExercise类来完成:

注意上面修改的HighExercise类中的getPrice()方法应该恢复原先。

package com.ygt.principle.ocp;

public class DiscountHighExercise extends HighExercise{

    public DiscountHighExercise(Double price, String name) {
        super(price, name);
    }

    // 重写获取价格方法
    @Override
    public Double getPrice() {
        // 增加价格为原来的85折。
        return super.getPrice() * 0.85;
    }
}

再稍微修改下ExerciseStore类即可:

package com.ygt.principle.ocp;

import java.util.ArrayList;
import java.util.List;

/**
 * 习题店 专门卖习题集的
 */
public class ExerciseStore {


    // 习题店中包含各种习题集
    private List<IExercise> exerciseList = new ArrayList<>();

    // 初始化习题集
    public ExerciseStore() {
        // 修改地方,将创建类改成DiscountHighExercise
        exerciseList.add(new DiscountHighExercise(63d, "五年高考三年模拟数学"));
        exerciseList.add(new DiscountHighExercise(53d, "五年高考三年模拟语文"));
        exerciseList.add(new DiscountHighExercise(43d, "五年高考三年模拟英语"));
    }

    // 展示习题集方法
    public void showExercise() {
        System.out.println("~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~");
        System.out.println("习题名\t\t\t\t\t价格\t\t");
        exerciseList.forEach(e-> System.out.println(e.getName() + "\t\t¥" + e.getPrice() + "元\t\t"));
    }

    // 测试调用习题集
    public static void main(String[] args) {
        ExerciseStore store = new ExerciseStore();
        store.showExercise();
    }
}

再看下执行结果:

~~~~~~~~~~~~~~本店拥有的高中习题集~~~~~~~~~~~~~~~
习题名					价格		
五年高考三年模拟数学		¥53.55元		
五年高考三年模拟语文		¥45.05元		
五年高考三年模拟英语		¥36.55

这样通过增加一个DiscountHighExercise类,修改ExerciseStore中少量的代码,就可以实现习题集价格的85折的需求啦,而其他部分没有任何变动,体现了开闭原则的应用。

注意的一点:开闭原则是对扩展开放,对修改关闭,但这并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。

🌸 完结

相信各位看官看到这里大致都对设计模式中的其中一个原则有了了解吧,开闭原则实际上的定义就是扩展开放,对修改关闭,提高软件系统的可复用性及可维护性。

学好设计模式,让你感受一些机械化代码之外的程序设计魅力,也可以让你理解各个框架底层的实现原理。最后,祝大家跟自己能在程序员这条越走越远呀,祝大家人均架构师,我也在努力。 接下来期待第三话:依赖倒转原则。 💪💪💪

文章的最后来个小小的思维导图:
在这里插入图片描述

🧐 本人不才,如有什么缺漏、错误的地方,也欢迎各位人才们评论批评指正!🤞🤞🤞

🤩 当然如果这篇文章确定对你有点小小帮助的话,也请亲切可爱的人才们给个点赞、收藏下吧,非常感谢!🤗🤗🤗

🥂 虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!✨✨✨

💟 感谢各位看到这里!愿你韶华不负,青春无悔!让我们一起加油吧! 🌼🌼🌼

💖 学到这里,今天的世界打烊了,晚安!🌙🌙🌙

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java基础学习——字符流

1.为什么会出现字符流&#xff1a; 由于字节流 操作中文不是特别的方便&#xff0c;所以java就提供字符流 字符流字节流编码表 用字节流复制文本文件时&#xff0c;文本文件也会有中文&#xff0c;但是没有问题&#xff0c;原因是最终底层操作会自动进行字节拼接成中文&#xf…

摄影入门 | 相机的基本原理

一、获取图像——小孔成像实验 小孔成像实验中&#xff0c;点燃蜡烛&#xff0c;会在小孔另一面的白纸上看到一个倒立的烛焰。 此现象可以用来解释物理学原理&#xff1a;光在同种均匀介质中&#xff0c;在不受引力作用干扰的情况下沿直线传播。 这样&#xff0c;我们就用一种…

从零开始搭建游戏服务器 第一节 创建一个简单的服务器架构

目录引言技术选型正文创建基础架构IDEA创建项目添加Netty监听端口编写客户端进行测试总结引言 由于现在java web太卷了&#xff0c;所以各位同行可以考虑换一个赛道&#xff0c;做游戏还是很开心的。 本篇教程给新人用于学习游戏服务器的基本知识&#xff0c;给新人们一些学习…

伪静态技术

网址和纯静态一样&#xff0c;只是&#xff0c;其内部仍旧需要查询数据库&#xff1a;如果有一个页面&#xff0c;希望这个页面利于seo,但是有不适合使用真静态&#xff0c;比如csdn论坛帖子&#xff0c;可以考虑使用伪静态&#xff0c;即: 形式上是一个静态地址&#xff0c;比…

Chapter7.2:MATLAB在频率法中的应用及频率法稳定性分析

该系列博客主要讲述Matlab软件在自动控制方面的应用&#xff0c;如无自动控制理论基础&#xff0c;请先学习自动控制系列博文&#xff0c;该系列博客不再详细讲解自动控制理论知识。 自动控制理论基础相关链接&#xff1a;https://blog.csdn.net/qq_39032096/category_10287468…

PyTorch 深度学习实战 | DIEN 模拟兴趣演化的序列网络

01、实例&#xff1a;DIEN 模拟兴趣演化的序列网络深度兴趣演化网络(Deep Interest Evolution Network,DIEN)是阿里巴巴团队在2018年推出的另一力作,比DIN 多了一个Evolution,即演化的概念。在DIEN 模型结构上比DIN 复杂许多,但大家丝毫不用担心,我们将DIEN 拆解开来详细地说明…

Intel 处理器 macOS降级到Big Sur

1 创建可引导的 macOS 安装器 将移动硬盘作安装 Mac 操作系统的启动磁盘。 创建可引导安装器需要满足的条件 移动硬盘&#xff08;格式化为 Mac OS 扩展格式&#xff09;&#xff0c;至少有 14GB 可用空间已下载 macOS Big Sur的安装器 2 下载 macOS macOS Big Sur安装器会…

【GPT4】微软 GPT-4 测试报告(1)总体介绍

欢迎关注【youcans的AGI学习笔记】原创作品&#xff0c;火热更新中 微软 GPT-4 测试报告&#xff08;1&#xff09;总体介绍 微软 GPT-4 测试报告&#xff08;2&#xff09;多模态与跨学科能力 微软 GPT-4 测试报告&#xff08;3&#xff09;GPT4 的编程能力 【GPT4】微软 GPT-…

Thingsboard使用gateway网关

简介&#xff1a; 本次是想测试一下thingsboard网关的使用&#xff0c;实现通过网关mqttthingsboardemqx 实现间接设备创建和数据传输 前期准备&#xff1a; thingsboard平台 thingsboard网关 emqx平台 MQTTX工具 详细过程&#xff1a; 1&#xff1a;thingsboard平台搭建 …

字节、阿里等大厂年薪50w+的测试都什么水平?

各位做测试的朋友&#xff0c;但凡经历过几次面试&#xff0c;那么你一定曾被问到过以下问题&#xff1a; 1、在Linux环境下&#xff0c;怎么执行web自动化测试&#xff1f; 2、Shell如何&#xff0c;Docker熟悉吗&#xff1f; 3、全链路的压测实操过吗&#xff0c;如何推进与开…

FasterNet实战:使用FasterNet实现图像分类任务(一)

文章目录摘要安装包安装timm安装 grad-cam数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集摘要 论文翻译&#xff1a;https://wanghao.blog.csdn.net/article/details/129485972?spm1001.2014.3001.5502 官方源码&#xff1a; https://github.com/JierunChen/Faste…

VR实景导航,解决最后几十米的导航问题

你是否跟朋友有过这样的经历&#xff1a;“哎&#xff0c;你说的那个餐厅在哪呀&#xff1f;”&#xff0c;“这家商场好复杂&#xff0c;怎么转啊”&#xff0c;“你在医院哪一层&#xff1f;我怎么找不到你呀&#xff01;”等等。在建筑内部&#xff0c;我们的地图导航并不是…

在U盘上运行的 Windows

版本&#xff1a;5.6.1平台&#xff1a;Win x64语言&#xff1a;简体中文,繁体中文,英文更新时间&#xff1a;2023-03-04 下载地址&#xff1a;https://dl.luobotou.org/wtga5610.zip 解压后运行WTGA文件夹中的wintogo.exe启动程序。从5.5版本开始不再支持32位系统、Win7系统…

HTTP协议加强

HTTP协议加强 Date: January 19, 2023 Sum: HTTP请求、响应、请求方法、响应状态代码 HTTP协议简介 什么是通信 通信&#xff0c;就是信息的传递和交换。 通信三要素&#xff1a;通信的主体、通信的内容、通信的方式 现实生活中的通信 案例&#xff1a;张三要把自己考上传…

美颜SDK技术原理、技术应用、代码分析

随着社交媒体的普及&#xff0c;人们对于自己的外貌越来越重视。为了满足用户对于美颜需求&#xff0c;各大科技公司纷纷推出了美颜SDK技术&#xff0c;使得用户可以在拍照和视频中实现美颜效果。本文将对美颜SDK技术进行详细分析。 一、美颜SDK技术的原理 美颜SDK技术是一种基…

精简指令集结构(Reduced Instruction Set Computer,RISC)

ARM内核采用精简指令集结构&#xff08;Reduced Instruction Set Computer&#xff0c;RISC&#xff09;体系结构。RISC技术产生于20世纪70年代&#xff0c;其设计目标是创建一种能以每个时钟周期执行一条指令的速度很快的计算机。RISC的设计重点在于降低由硬件执行的指令复杂度…

Kubeadm生成的k8s证书内容说明以及延长证书过期时间

Kubeadm生成的k8s证书内容说明Kubeadm生成的k8s证书内容说明&#xff1a;证书分组Kubernetes 集群根证书由此根证书签发的证书有:kube-apiserver 代理根证书(客户端证书)etcd 集群根证书etcd server 持有的服务端证书peer 集群中节点互相通信使用的客户端证书pod 中定义 Livene…

函数的定义与使用及七段数码管绘制

函数的定义 函数是一段代码的表示 函数是一段具有特定功能的、可重用的语句组 函数是一种功能的抽象&#xff0c;一般函数表达特定功能 两个作用&#xff1a;降低编程难度 和 代码复用 求一个阶乘 fact就是 函数名 n就是参数 return就是输出部分即返回值 而函数的调用就是…

【计量】回归背后的微操作——论文自救记录(进行中)

【计量】回归背后的微操作 1. 变量的选择 与 模型的设定 https://zhuanlan.zhihu.com/p/50577508?yidian_smb 2. 变量的处理 2.1 常用的处理——中心化、标准化、归一化 目的&#xff1a;统一量纲&#xff08;Scale&#xff09;—— 可以理解成 100分制下&#xff0c;1 2分…

Spring Security 6.0系列【2】认证篇之使用数据库存储用户

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 源码地址&#xff1a;https://gitee.com/pearl-organization/study-spring-security-demo 文章目录前言1. 环境搭建1.1 创建用户表1.…
最新文章