(学习打卡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、里氏替换原则改善代码

四、迪米特法则原则

五、接口隔离原则

六、依赖倒置原则

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

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

相关文章

K8S本地开发环境-minikube安装部署及实践

引言 在上一篇介绍了k8s的入门和实战,本章就来介绍一下在windows环境如何使用minikube搭建K8s集群,好了废话不多说,下面就和我一起了解Minikube吧。 什么是Minikube? Minikube 是一种轻量级的 Kubernetes 实现,可在本…

【docker】安装 Redis

查看可用的 redis版本 docker search redis拉取 redis最新镜像 docker pull redis:latest查看本地镜像 docker images创建挂在文件 mkdir -pv /test1/docker_volume/redis/datamkdir -pv /test1/docker_volume/redis/confcd /test1/docker_volume/redis/conf/touch redis.con…

IPC之十二:使用libdbus在D-Bus上异步发送/接收信号的实例

IPC 是 Linux 编程中一个重要的概念,IPC 有多种方式,本 IPC 系列文章的前十篇介绍了几乎所有的常用的 IPC 方法,每种方法都给出了具体实例,前面的文章里介绍了 D-Bus 的基本概念以及调用远程方法的实例,本文介绍 D-Bus…

[Angular] 笔记 23:Renderer2 - ElementRef 的生产版本

chatgpt: Renderer2 简介 在 Angular 中,Renderer2 是一个服务,用于处理 DOM 操作的抽象层。它提供了一种安全的方式来操作 DOM,同时与平台无关,有助于维护应用程序的跨浏览器兼容性和安全性。 Renderer2 的作用是在 Angular 组…

【C++】浅拷贝 / 深拷贝 / 写时拷贝

文章目录 1. 经典的string类问题2. 浅拷贝3. 深拷贝3.1 传统写法的String类3.2 现代写法的String类 4. 写时拷贝 1. 经典的string类问题 上一篇博客已经对string类进行了简单的介绍,大家只要能够正常使用即可。 链接:【C】string 在面试中,面…

20 太空漫游

效果演示 实现了一个太空漫游的动画效果,其中包括火箭、星星和月亮。当鼠标悬停在卡片上时,太阳和星星会变成黄色,火箭会变成飞机,月亮会变成小型的月亮。整个效果非常炫酷,可以让人想起科幻电影中的太空漫游。 Code &…

计算机网络(7):网络安全

网络安全问题 计算机网络上的通信面临以下的四种威胁: (1)截获(interception)攻击者从网络上窃听他人的通信内容。 (2)中断(interruption)攻击者有意中断他人在网络上的通信。 (3)篡改(modification)攻击者故意篡改网络上传送的报文。 (4)伪造(fabrication)攻击者伪造信息在网…

Python通过用户输入两个数字并计算两个

通过用户输入两个数字,并计算两个 以下实例为通过用户输入两个数字,并计算两个数字之和: 实例(Python 3.0) # -*- coding: UTF-8 -*-# Filename : test.py # author by : www.dida100.com# 用户输入数字 num1 input(输入第一个数字&#…

C# WinForm MessageBox自定义按键文本 COM组件版

c# 更改弹窗MessageBox按钮文字_c# messagebox.show 字体-CSDN博客 需要用到大佬上传到百度云盘的Hook类,在大佬给的例子的基础上改动了点。 加了ok按键,还原了最基础的messageBox。 为了适配多语言,增加ReadBtnLanguge方法。 应用时自己…

开发辅助三(缓存Redisson分布式锁+分页插件)

缓存 缓存穿透:查询一个不存在的数据,由于缓存不命中,将大量查询数据库,但是数据库也没有此记录。 没有将这次查询的null写入缓存,导致了这个不存在的数据每次请求都要到存储层查询,失去了缓存的意义。 解…

export .... 配置环境变量,环境变量都存去哪里了?

今天在配置镜像环境的时候,在纠结执行如下命令之后,这个环境变量会保存到哪里?然后找了.bash_profile和.zshrc文件都没有找到,在纠结乱存到哪里去了 export HOMEBREW_API_DOMAIN"https://mirrors.tuna.tsinghua.edu.cn/home…

复试 || 就业day02(2024.01.02)项目一

文章目录 前言最小二乘法的推导使用正规方程求解 y w x b ywxb ywxb多元线性回归 y w 1 x 1 w 2 x 2 b yw1x1w2x2b yw1x1w2x2b总结 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫本文内容来自某机构网课&#xff…

详解 docker 镜像制作的两种方式

概要 制作Docker镜像一般有2种方法: 通过Dockerfile,完成镜像的创建使用仓库中已有的镜像,安装自己使用的软件环境后完成新镜像创建 docker 常用命令 docker build: 用于构建 Docker 镜像。该命令可以从 Dockerfile 构建镜像,…

2022年12月10日-2023年12月28日

好久没写文章了,也就是好久没写流水账了.今天写的,到底是生日,还是记录这一年的工作,比较模糊,时间上来讲,两个用意合一起吧. 这一年,是极其艰苦的一年,也是不堪回首的一年.3月份的时候设宴欢送朋友离开深圳,回住处上楼时跌倒入院,之后开刀.家人们都从老家赶来,照顾了我好几天.…

Debezium发布历史43

原文地址: https://debezium.io/blog/2018/12/05/automating-cache-invalidation-with-change-data-capture/ 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. 通过更改数据捕获自动使缓存失效 2018 年…

文本表示模型简介

文本是一类非常重要的非结构化数据,如何表示文本数据一直是机器学习领域的一个重要研究方向。那么有哪些文本表示模型?以及它们各有什么优缺点? 1. 常见的文本表示模型 1.1. 词袋模型和N-gram模型 最基础的文本表示模型是词袋模型。顾名思…

QML —— RadioButton的两个经典示例(附完整源码)

示例1-效果 示例2-效果 实例1 - 源码 import QtQuick 2.12 import QtQuick.Window 2.12import QtQuick.Layouts 1.12 import QtQuick.Controls 2.5Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Text{id: classNametext: qsTr("--&quo…

CSS-5

移动端适配 屏幕分辨率 屏幕分辨率:纵横向上的像素点数,单位是px电脑常见分辨率:1920 * 10801336 * 768...硬件分辨率 -> 物理分辨率(出厂设置) 缩放调节后的分辨率 -> 逻辑分辨率(软件/驱动设置&a…

Web网页开发-CSS层叠样式表1-笔记

1.CSS的引入方式 (1)内嵌式:把style双标签写在head标签里面,可以影响同种标签 (2)行内式:把style写在标签内部,只能影响当前标签 (3)外链式:创建css文件,使用link将html文件和css文件连接起来 (4)导入式&am…

2024年美赛数学建模ABCDEF题思路选题分析

文章目录 1 赛题思路2 美赛比赛日期和时间3 赛题类型4 美赛常见数模问题5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 美赛比赛日期和时间 比赛开始时间:北京时间2024年2月2日(周五&#xff…