(学习打卡2)重学Java设计模式之六大设计原则

   前言:听说有本很牛的关于Java设计模式的书——重学Java设计模式,然后买了(*^▽^*)

开始跟着小傅哥学Java设计模式吧,本文主要记录笔者的学习笔记和心得。

打卡!打卡!

六大设计原则

(引读:这里的节奏是,先说一下概念定义,然后是模拟场景,最后是反例、正例。)

一、单一职责原则

1、定义

单一职责原则,它规定一个类应该只有一个发生变化的原因。

为什么?

因为如果开发的一个功能不是一次性的,当一个Class类负责超过两个及以上职责时,当需求不断迭代、实现类持续扩张,就会出现难以维护、不好扩展、测试难度大和上线风险高等问题。

2、模式场景

一个视频网站用户分类的例子:

  • 访问用户,只能看480P的高清视频,有广告
  • 普通会员,可以看720P的超清视频,有广告
  • VIP会员,付费的大哥,可以看1080P的蓝光视频,无广告
3、违背原则方案(反例)

根据上面的需求,直接编码,实现一个最简单的基本功能:根据不同的用户类型,判断用户可以观看的视频类型。

public class VideoUserService {
    public void serveGrade(String userType){
        if ("VIP用户".equals(userType)){
            System.out.println("VIP用户,视频1080P蓝光");
        } else if ("普通用户".equals(userType)){
            System.out.println("普通用户,视频720P超清");
        } else if ("访客用户".equals(userType)){
            System.out.println("访客用户,视频480P高清");
        }
    }
}

        如上,这一个类包含着多个不同的行为,多种用户职责,如果在这样的类上继续扩展功能就会显得很臃肿。比如再加一个“超级VIP会员”,可以超前点播,按上面的实现方式,只能继续ifelse。这样的代码结构每次迭代,新需求的实现都可能会影响到其他逻辑。

4、单一职责原则改善代码(正例)

        视频播放是视频网站的核心功能,当完成核心功能的开发后,就需要不断地完善用户权限,才能更好运营网站。其实就是不断建设用户权益,根据不同的用户类型提供差异化服务。

        为了满足不断迭代的需求,就不能向上面一样把所有职责行为混为一谈,而是应该提供一个上层的接口类,对不同的差异化用户给出单独的实现类,拆分各自的职责。

(1)定义接口

public interface IVideoUserService {
    
    // 视频清晰级别;480P、720P、1080P
    void definition();

    // 广告播放方式;无广告、有广告
    void advertisement();
}

        定义出上层接口IVideoUserService,统一定义需要实现的功能,包括视频清晰级别接口definition()、广告播放方式接口advertisement()。然后三种不同类型的用户就可以分别实现自己的服务类,做到职责统一。

(2)实现类

        1)访问用户,只能看480P的高清视频,有广告

public class GuestVideoUserService implements IVideoUserService {
    
    public void definition() {
        System.out.println("访客用户,视频480P高清");
    }

    public void advertisement() {
        System.out.println("访客用户,视频有广告");
    }
}

        2)普通会员,可以看720P的超清视频,有广告

public class OrdinaryVideoUserService implements IVideoUserService {

    public void definition() {
        System.out.println("普通用户,视频720P超清");
    }

    public void advertisement() {
        System.out.println("普通用户,视频有广告");
    }

}

        3)VIP会员,付费的大哥,可以看1080P的蓝光视频,无广告

public class VipVideoUserService implements IVideoUserService {

    public void definition() {
        System.out.println("VIP用户,视频1080P蓝光");
    }

    public void advertisement() {
        System.out.println("VIP用户,视频无广告");
    }

}
5、易扩展示例

        假设有新的需求如下:7天试用VIP会员,可以试用看1080P的蓝光视频,但是有广告。

// 7天试用VIP用户
public class TryVipVideoUserService implements IVideoUserService {

    public void definition() {
        System.out.println("7天试用VIP用户,视频1080P蓝光");
    }

    public void advertisement() {
        System.out.println("7天试用VIP用户,视频有广告");
    }

}

        在项目开发的过程中,尽可能保证接口的定义、类的实现以及方法开发保持单一职责,对项目后期的迭代和维护是很好的。

二、开闭原则

1、定义

在面向对象编程领域中,开闭原则规定软件的对象、类、模块和函数对扩展应该是开放的,但是对于修改是封闭的。

这就意味着应该用抽象定义结构,用具体实现扩展细节,以此确保软件系统开发和维护过程的可靠性。

开闭原则的核心思想可以理解为面向抽象编程。

小结:对扩展是开放的,对修改是封闭的。

2、模拟场景

 对于外部调用方,只要能体现出面向抽象编程,定义出接口并实现其方法,即不修改原有方法体,只通过继承方式进行扩展,都可以体现出开闭原则。

 (1)场景案例

计算三种形状的面积,长方形、三角形,圆形。其中圆的π=3.14,但后续由于π的取值精度不适用于后面的场景,需要再扩展,接下来模拟这个场景来体现开闭原则。

(2)定义接口

public interface ICalculationArea {

    /**
     * 计算面积,长方形
     *
     * @param x 长
     * @param y 宽
     * @return 面积
     */
    double rectangle(double x, double y);

    /**
     * 计算面积,三角形
     * @param x 边长x
     * @param y 边长y
     * @param z 边长z
     * @return  面积
     *
     * 海伦公式:S=√[p(p-a)(p-b)(p-c)] 其中:p=(a+b+c)/2
     */
    double triangle(double x, double y, double z);

    /**
     * 计算面积,圆形
     * @param r 半径
     * @return 面积
     *
     * 圆面积公式:S=πr²
     */
    double circular(double r);

}

 (3)实现类

特别地,这里的π取3.14D,这也是要扩展精度的方法和体现开闭原则的地方。

public class CalculationArea implements ICalculationArea {

    private final static double π = 3.14D;

    public double rectangle(double x, double y) {
        return x * y;
    }

    public double triangle(double x, double y, double z) {
        double p = (x + y + z) / 2;
        return Math.sqrt(p * (p - x) * (p - y) * (p - z));
    }

    public double circular(double r) {
        return π * r * r;
    }

}
3、违背原则方案

如果不考虑开闭原则,也不考虑整个工程服务的使用情况,直接改π值。

private final static double π = 3.141592653D;
4、开闭原则改善代码

更好的做法,按照开闭原则。继承父类,扩展需要的方法,同保留原有的方法,新增自己需要的方法。它的主要目的是不能因为个例需求的变化二改变预定的实现类。

public class CalculationAreaExt extends CalculationArea {

    private final static double π = 3.141592653D;

    @Override
    public double circular(double r) {
        return π * r * r;
    }

}

扩展后的方法满足了π精度变化的需求,需要使用此方法的用户可以直接调用。而其他的方法,也不影响继续使用。

三、里氏替换原则

1、定义

2、模拟场景

3、违背原则方案

4、里氏替换原则改善代码

四、迪米特法则原则

五、接口隔离原则

六、依赖倒置原则

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

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

相关文章

最新-mybatis-plus 3.5分页插件配置

mybatis-plus 3.5分页插件配置 前提 1.项目不是springboot, 是以前的常规spring项目 2.mp 从3.2升级到3.5,升级后发现原本的分页竟然不起作用了,每次查询都是查出所有 前后配置对比 jar包对比 jsqlparser我这里单独引了包,因为版本太低…

[蓝桥杯2020国赛]答疑

答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下: 首先进入办公室,编号为 i 的同学需要 si​ 毫秒的时间。然后同学问…

深入理解SPi通讯协议

目录 SPI简介: 主设备通过选择线(SS) 主设备通过时钟线(SCLK) 主设备通过主输出线(MOSI) 主设备通过主输出线(MISO) SPI读写数据: SPI写入数据&#xf…

超详细解释奇异值分解(SVD)【附例题和分析】

目录 一. 矩阵对角化 二. 奇异值分解 三. 对比奇异值分解与特征值分解 四. SVD分解与四大基础子空间 五. SVD分解的正交矩阵 六. 方阵与SVD分解 七. 单位特征向量与SVD分解 八. 例题分析:秩为1 九. 例题分析:秩为2 十. 计算机网络与矩阵的秩 一…

从董宇辉小作文风波,我们普通人能学到些什么?

哈喽,大家好啊,我是雷工! 最近董宇辉小作文风波动静太大了,哪哪都是。 打开公号上都在写董宇辉,打开某音,都在说董宇辉。 这种事其实本来就是立场不同,各个角度来说都有道理的事。 神仙打架&am…

利用深度学习图像识别技术实现教室人数识别

引言 在现代教育环境中,高效管理和监控教室成为了一个重要议题。随着人工智能技术的迅猛发展,特别是深度学习和图像识别领域的突破,我们现在可以通过智能系统来自动识别教室内的人数,从而实现更加智能化的教室管理。 深度学习与图…

手把手教你开发盲盒小程序

在这个数字时代,微信小程序已经成为了各大品牌和个人的主要营销渠道。而盲盒小程序,作为小程序领域中的一种独特类型,更是具有巨大的市场潜力。那么,如何创建和运营一个成功的微信盲盒小程序呢?以下是一份保姆级的教程…

SpringBoot之多环境开发配置

1 多环境开发配置 问题导入 在实际开发中,项目的开发环境、测试环境、生产环境的配置信息是否会一致?如何快速切换? 1.1 多环境启动配置 yaml文件多环境启动 不同环境使用—隔开 示例代码: spring:profiles:active: dev#生产…

Intellij IDEA 快速开发参考

快捷键 核心快捷键 IntelliJ IDEA 作为一个以快捷键为中心的 IDE,为大多数操作建议了键盘快捷键。在这个主题中,您可以找到最不可缺少的列表,使 IntelliJ IDEA 轻松实现第一步。 核心快捷键表: 操作快捷键根据名称查找操作CtrlSh…

阶段十-分布式-Redis02

第一章 Redis 事务 1.1 节 数据库事务复习 数据库事务的四大特性 A:Atomic ,原子性,将所以SQL作为原子工作单元执行,要么全部执行,要么全部不执行;C:Consistent,一致性&#xff0…

Django 分页(表单)

目录 一、手动分页二、分页器分页 一、手动分页 1、概念 页码:很容易理解,就是一本书的页码每页数量:就是一本书中某一页中的内容(数据量,比如第二页有15行内容),这 15 就是该页的数据量 每一…

【信号处理:小波包转换(WPT)/小波包分解(WPD) 】

【信号处理:小波包转换(WPT)/小波包分解(WPD) 】 小波包变换简介WPT/WPD的基础知识WPT/WPD的主要特点The Wavelet Packet Transform 小波包变换前向小波数据包变换最佳基础和成本函数数学中波纹的最佳基础其他成本函数…

【教学类-43-14】 20240103 (4宫格数独:正确版:576套) 不重复的基础模板数量:576套

作品展示::——4宫格 576套不重复模板(48页*12套题) 背景需求: 生成4宫格基础模板768套,观看64页内容时,明显看到有错误 【教学类-43-13】 20240103 (4宫格数独:错误版…

kbdnso.dll文件缺失,软件或游戏报错的快速修复方法

很多小伙伴遇到电脑报错,提示“kbdnso.dll文件缺失,程序无法启动执行”时,不知道应该怎样处理,还以为是程序出现了问题,想卸载重装。 首先,先要了解“kbdnso.dll文件”是什么? kbdnso.dll是Win…

高压功率放大器的作用或应用领域是什么

高压功率放大器是一种能够将低电压信号放大到高电压水平的设备。它在各个领域中扮演着重要的角色,并具有广泛的应用。本文将介绍高压功率放大器的作用和应用领域。 高压功率放大器可以在音频设备中发挥重要作用。音频设备中需要将低音频信号放大到足够的水平&#x…

控制台日志存入数据库后结果乱码

控制台输出 数据库返回 结论 控制台的输出在存储到数据库之后出现了ANSI颜色代码。这些颜色代码通常是由控制台日志库添加的,用于在支持ANSI颜色代码的终端中显示彩色文本。例如: [95m6 [0m | [95m0.6376 [0m | [95m0.0 [0m | [95m289.2 [0m | 在上面的…

MySQL主从复制案例实现

使用Sharding-JDBC实现读写分离&#xff1a; 1、导入maven坐标 2、 在配置文件中配置读写分离规则 3、在配置文件中配置允许bean定义覆盖配置项 1、导入maven坐标 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jd…

Java安装详细教程

文章目录 一、JDK 下载 和 安装1.1 选择 Java版本1.2 下载 JDK 二、 配置环境变量2.1 配置环境变量的原因2.2 配置环境变量2.3 验证配置是否成功 参考资料 一、JDK 下载 和 安装 1.1 选择 Java版本 访问 Oracle 官方网站的 Java 下载页面Java Archive | Oracle。 在 “Java …

机器学习常用算法模型总结

文章目录 1.基础篇&#xff1a;了解机器学习1.1 什么是机器学习1.2 机器学习的场景1.2.1 模式识别1.2.2 数据挖掘1.2.3 统计学习1.2.4 自然语言处理1.2.5 计算机视觉1.2.6 语音识别 1.3 机器学习与深度学习1.4 机器学习和人工智能1.5 机器学习的数学基础特征值和特征向量的定义…

软件测试作业‖pytest+po+csv+html报告+cookie+selenium

软件测试作业‖pytestpocsvhtml报告cookieselenium 先用本地部署的系统试了下 或者UFT自动化测试里诺图书管理系统软件测试 # &#xff0c;#测试报告# #性能测试#&#xff0c;#测试用例#&#xff0c; #自动化测试# Selenium 的 Web自动化测试基本要求和注意事项 1.请使用ch…