当前位置: 首页 > news >正文

(学习打卡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、1080Pvoid 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;@Overridepublic double circular(double r) {return π * r * r;}}

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

三、里氏替换原则

1、定义

2、模拟场景

3、违背原则方案

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

四、迪米特法则原则

五、接口隔离原则

六、依赖倒置原则

相关文章:

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

前言:听说有本很牛的关于Java设计模式的书——重学Java设计模式,然后买了(*^▽^*) 开始跟着小傅哥学Java设计模式吧,本文主要记录笔者的学习笔记和心得。 打卡!打卡! 六大设计原则 (引读:这里…...

数据结构:第7章:查找(复习)

目录 顺序查找: 折半查找: 二叉排序树: 4. (程序题) 平衡二叉树: 顺序查找: ASL 折半查找: 这里 j 表示 二叉查找树的第 j 层 二叉排序树: 二叉排序树(Binary Search Tree&…...

编程语言的未来?

编程语言的未来? 随着科技的飞速发展,编程语言在计算机领域中扮演着至关重要的角色。它们是软件开发的核心,为程序员提供了与机器沟通的桥梁。那么,在技术不断进步的未来,编程语言的走向又将如何呢? 在技…...

SpringBoot的测试

🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全栈,…...

C++睡眠函数:Windows平台下的Sleep函数和Linux平台的usleep函数

C/C睡眠函数:Windows平台下的Sleep函数和Linux平台的usleep函数 WinAPI Sleep Sleep函数属于Windows API,使用它需要先包含synchapi.h。 void Sleep(DWORD dwMilliseconds);函数仅有一个参数(睡眠时长),单位是毫秒。…...

详解白帽子以及红队、蓝队和紫队

企业继续数字化,其关键基础设施和运营扩大了攻击面,暴露于各种威胁途径的面前。为了解决这个问题,企业领导者认识到拥有内部专家的重要性。考虑到网络威胁领域不断发展的态势,企业领导者可以利用道德黑客以及红队、蓝队和紫队的工…...

1、docker常用技巧:docker数据位置更改

目录 🍅点击这里查看所有博文 随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记…...

Qt之设置QLabel的背景色和前景色

方法有两种,一种是使用调色板,一种是使用样式表。 方法一:调色板 QPalette palette ; // 设置黑底绿字 palette .setColor(QPalette::Background, Qt::black); palette .setColor(QPalette::WindowText, Qt::green); // 这句不能少,否则没效果 ui->label->setAutoF…...

数模学习day06-主成分分析

主成分分析(Principal Component Analysis,PCA)主成分分析是一种降维算法,它能将多个指标转换为少数几个主成分,这些主成分是原始变量的线性组合,且彼此之间互不相关,其能反映出原始数据的大部分信息。一般来说当研究的问题涉及到…...

Windows PowerShell的安全目标——安全警报

Windows PowerShell的安全目标——安全警报 1. 保证Shell安全 ​ 自从2006年年底PowerShell发布以来,微软在安全和脚本方面并没有取得很好的名声。毕竟那个时候,**VBScript和Windows Script Host(WSH)**是两个最流行的病毒和恶意软件的载体&#xff0c…...

k8s笔记1- 初步认识k8s

k8s简介: kubernetes,俗称k8是,用于自动部署,扩缩和管理容器化应用程序的开源系统,它将组成应用程序的容器,组合成逻辑单元,便于管理和服务发现。 k8s的作用 自动化上线和回滚、存储编排…...

ARM CCA机密计算软件架构之内存加密上下文(MEC)

内存加密上下文(MEC) 内存加密上下文是与内存区域相关联的加密配置,由MMU分配。 MEC是Arm Realm Management Extension(RME)的扩展。RME系统架构要求对Realm、Secure和Root PAS进行加密。用于每个PAS的加密密钥、调整或加密上下文在该PAS内是全局的。例如,对于Realm PA…...

python基于flask实现一个文本问答系统

from flask import Flask, render_template, requestapp Flask(__name__)# 一个简单的问题-答案映射,实际中可以使用更复杂的存储结构(数据库等) qa_pairs {"什么是人工智能?": "人工智能是模拟人类智能的一种机…...

lambda表达式使用和示例

lambda表达式 什么是lambda 学习lamdba有两个结构十分关键,一个是lamdba自己,另一个是函数式接口 lamdba lamdba表达式本质上就是匿名方法,不能独立运行用于实现函数式接口定义的另一个方法,因此lamdba会产生一个匿名类lamdba…...

STM32学习笔记十八:WS2812制作像素游戏屏-飞行射击游戏(8)探索游戏多样性,范围伤害模式

前面我们的攻击手段比较单一,虽然已经分出了 EnemyT1 / EnemyT2 / EnemyT3, 但里面还是基本一样的。这回,我们尝试实现一些新的攻击方法,实现一些新的算法。 1、前面我们小飞机EnemyT1 的攻击方式是垂直向下发射子弹。 那么大飞机…...

C#获取windows系统资源使用情况

1.前言 之前有一篇博客介绍如何获取Linux服务器上的资源使用情况《Java 获取服务器资源(内存、负载、磁盘容量)》,这里介绍如何通过C#获取Window系统的资源使用。 2.获取服务器资源 2.1.内存 [DllImport("kernel32.dll")][retu…...

PE解释器之PE文件结构

PE文件是由许许多多的结构体组成的,程序在运行时就会通过这些结构快速定位到PE文件的各种资源,其结构大致如图所示,从上到下依次是Dos头、Nt头、节表、节区和调试信息(可选)。其中Dos头、Nt头和节表在本文中统称为PE文件头(因为SizeOfHeaders…...

Android—— MIPI屏调试

一、实现步骤 1、在kernel/arch/arm/boot/dts/lcd-box.dtsi文件中打开&dsi0节点,关闭其他显示面板接口(&edp_panel、&lvds_panel) --- a/kernel/arch/arm/boot/dts/lcd-box.dtsib/kernel/arch/arm/boot/dts/lcd-box.dtsi-5,14 …...

BLE协议—协议栈基础

BLE协议—协议栈基础 BLE协议栈基础通用访问配置文件层(Generic Access Profile,GAP)GAP角色设备配置模式和规程安全模式广播和扫描 BLE协议栈基础 蓝牙BLE协议栈包含三部分:主机、主机接口层和控制器。 主机:逻辑链路…...

yolov8知识蒸馏代码详解:支持logit和feature-based蒸馏

文章目录 1. 知识蒸馏理论2. yolov8 蒸馏代码应用2.1 环境配置2.2 训练模型(1) 训练教师模型(2) 训练学生模型baseline(3) 蒸馏训练3. 知识蒸馏代码详解3.1 蒸馏参数设置3.2 蒸馏损失代码讲解3.2.1 Feature based loss3.2.1 Logit loss3.3 获取蒸馏的feature map及channels...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

python/java环境配置

环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

ESP32读取DHT11温湿度数据

芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

MMaDA: Multimodal Large Diffusion Language Models

CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

爬虫基础学习day2

# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...