java设计模式(持续更新中)

1 设计模式介绍

  1. 设计模式代表了代码的最佳实践,被有经验的开发人员使用。
  2. 设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结。
  3. 使用设计模式是为了重用代码,并让代码更容易被人理解,保证代码的可靠性。
  4. 对接口编程而不是对实现编程
  5. 有限使用对象组合而不是继承关心

2 设计模式七大原则

  1. 单一职责原则:一个类应该只有一个引起它变化的原因。
  2. 开闭原则:软件实体应对扩展开放,对修改封闭。
  3. 里氏替换原则:子类型必须能够替换掉它们的基类型。
  4. 依赖倒置原则:高层模块不应依赖于低层模块,两者都应依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。
  5. 接口隔离原则:使用多个专门的接口比使用单一的总接口更好。
  6. 合成/聚合复用原则:尽量使用对象的组合/聚合,而不是继承关系达到复用的目的。
  7. 迪米特法则(最少知道原则):一个对象应对其他对象有尽可能少的了解。

      原文链接:https://blog.csdn.net/m0_54187478/article/details/136165351

     设计模式--七大原则 - 简书 (jianshu.com)

     以下内容均是借鉴上诉链接

3、设计原则详解

3.1单一职责原则

单一职责原则(Single Responsibility Principle, SRP)指一个类应该仅有一个引起它变化的原因。这意味着一个类应该只负责一项职责。即一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1、A2。

        通俗地讲,单一职责原则就像是说,一个人只应该有一个工作。想象你有一个朋友,他既是厨师也是司机。如果有一天他因为烹饪而分心,导致开车出事了,那就是因为他承担了太多的责任。在编程中,如果一个类同时负责多件事情(比如,既存储数据又显示数据),那么当其中一部分需要改变时,很容易影响到其他部分。遵循单一职责原则,意味着每个类只负责一件事情,这样当需求变化时,只需修改有限的部分,减少错误,使代码更容易维护和理解。

3.2开闭原则

开闭原则(Open-Closed Principle, OCP)是面向对象设计的核心原则之一,它指出软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着在不修改现有代码的情况下,应该能够添加新功能。也就是当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。用抽象构建框架,用实现扩展细节。

        开闭原则就像是给你的应用程序装上了一个“扩展插槽”,让你可以随时增加新功能而不需要打开机器去重新焊接电路板。想象一下,如果你有一个游戏机,每当出现新游戏时,你不需要更换游戏机内部的硬件就能玩,只需要购买新的游戏卡带插上去即可。这样,游戏机的设计就允许了扩展(新增游戏),而不需要修改(打开游戏机更换部件),这正是开闭原则的精髓。

3.3依赖倒置原则

        依赖倒置原则(Dependency Inversion Principle, DIP)指的是高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。这个原则的核心在于促进系统的解耦,从而使得系统更易于扩展和维护。(程序要依赖于抽象接口,不要依赖于具体实现) 它是开闭原则的基础。

比如有个Person类,可以接受Email、QQ和微信的消息。如果都为其提供一个专门的方法,就会让代码非常的冗余:

可以引入一个IReceiver接口,让Person类依赖该接口。这样QQ、微信和Email各自实现IReceiver里面的方法即可:

        依赖倒置原则(Dependency Inversion Principle, DIP)的核心思想是高层模块不应该依赖低层模块,它们都应该依赖于抽象;抽象不应该依赖细节,细节应该依赖抽象。用通俗的语言来说,就像是建筑的设计不应该基于具体的砖块类型,而是基于砖块的一般特性。这样,无论使用什么样的砖块,只要符合这些特性,就能构建出建筑。在编程中,这意味着我们的代码应该依赖于接口或抽象类,而不是具体的实现类,这样可以使代码更灵活、更易于维护和扩展。

3.4接口隔离原则

接口隔离原则(Interface Segregation Principle, ISP)强调不应该强迫客户依赖于它们不使用的接口。换句话说,更倾向于创建专门的接口而不是一个大而全的接口。 

列如:类A通过接口i依赖B,类C通过接口i依赖类D,如果接口i对于类A和类C来说不是最小接口,那么类B和类D必须去实现他们不需要的方法。

按隔离原则应当这样处理:将接口i拆分为独立的几个接口,将类分别与他们需要的接口建立依赖关系,也就是采用接口隔离原则。

        接口隔离原则(Interface Segregation Principle, ISP)讲的是不应该强迫客户依赖于它们不用的接口。用一个简单的例子来说,如果有一个多功能打印机,它可以打印、扫描和复印。根据接口隔离原则,我们不应该只有一个接口包含所有这些功能,因为不是每个使用打印机的人都需要扫描和复印的功能。相反,应该为打印、扫描和复印各自提供独立的接口。这样,只需要打印功能的用户就不必实现或依赖于扫描和复印的接口了。简而言之,接口隔离原则就是让接口更小、更专注,避免一个庞大的接口承担太多的职责。

3.5迪米特法则

迪米特法则(Law of Demeter, LoD),也称为最少知识原则,是一种软件开发的设计指导原则。它强调,一个对象应该对其他对象有尽可能少的了解,只与直接的朋友通信。直接的朋友指的是成员变量、方法参数或者对象创建的实例。 

        迪米特法则就像是说,一个人应该尽可能少地知道其他人的私事,只和直接的朋友交流。在编程中,这意味着一个类不应该知道太多其他类的细节,只和直接相关的类交互。这样做可以减少系统中的耦合,使得修改一个部分的时候,不会影响到太多其他部分,保持代码的整洁和可维护性。

3.6里氏替换原则

里氏替换原则(Liskov Substitution Principle)要求所有引用基类的地方必须能透明地使用其子类的对象。也就是在继承关系中,子类尽量不要重写父类的方法。继承实际上让两个类耦合性增强了,特别是运行多态比较频繁的时,整个继承体系的复用性会比较差。

比如一种极端情况:一个类继承了另一个类,但却重写了所有方法,那么继承的意义何在?说好的复用呢?        

解决方法是把原来的父类和子类都继承一个更通俗的基类,在适当的情况下,可以通过聚合,组合,依赖等来代替。

 

3.7合成复用原则

合成复用原则(Composite Reuse Principle)就是是尽量使用合成/聚合的方式,而不是使用继承。

        合成/聚合复用原则就像是搭积木。想象你正在建造一个小屋,你可以选择用预制的部分(比如窗户、门等)来组合成你想要的结构,而不是自己从头开始制造每一个部分。在编程中,这个原则告诉我们应该通过将现有的对象(积木块)组合起来来创建新的功能,而不是通过继承一个大而全的类(从零开始造一个整体)。这样做使得代码更加灵活,因为你可以随时替换或者重新组合这些“积木块”,而不是被固定在一种设计之中。

4、23种设计模式 

4.1创建模式(5种)

4.1.1单例模式

定义:单例模式确保一个类只有一个实例,并提供一个全局访问点。

单例模式可以分为两种:饿汉式懒汉式

优点: 

  1. 全局访问:提供了一个全局访问点,便于控制实例数量。
  2. 资源节约:避免了创建多个对象时的资源浪费。
  3. 线程安全:在多线程环境中,可以保证只创建一个实例。
  4. 控制实例化:可以控制对象的创建过程。

缺点:

  1. 代码耦合:单例模式可能会隐藏一些依赖关系,导致代码耦合。
  2. 可测试性差:由于单例模式是全局的,这使得单元测试变得困难。
  3. 内存浪费:单例对象在程序的整个生命周期内都占用内存。
  4. 滥用:单例模式有时会被滥用,导致程序设计不灵活。

适用场景:

  • 需要确保在整个应用程序中只存在一个实例的情况,如配置管理器、线程池、缓存等。

 方式一:饿汉式单例

/*** 预实例化单例类* 该类实现了Singleton模式,确保一个类只有一个实例,并提供对该实例的全局访问点* 使用静态预实例化方式,避免了同步加载的性能开销,适用于多线程环境*/
public class PreloadSingleton {// 单例实例,静态成员变量,在类加载时完成实例化private static PreloadSingleton instance=new PreloadSingleton();// 私有构造方法,防止外部通过new创建实例private PreloadSingleton(){// 初始化操作(如果有的话)}/*** 获取单例实例的方法* @return PreloadSingleton的唯一实例*/public static PreloadSingleton getInstance(){// 返回单例实例return instance;}
}

 可以很明显看出这种方式,在没有使用该单例对象时,该对象就被加载到内存,会造成内存的浪费。但是这种方式没有线程安全。

方式二:懒汉式式单例

为了避免内存的浪费,我们可以采用懒加载,即用到该单例对象的时候再创建。

public class Singleton {// 单例实例,私有静态变量private static Singleton instance ;/*** 私有构造方法,防止外部实例化*/private Singleton(){}/*** 获取单例实例的方法* 如果实例不存在,则创建一个新的实例并返回* 如果实例已经存在,则直接返回该实例* @return Singleton的唯一实例*/public static Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}
}

懒汉式虽然不浪费内存,但是无法保证线程的安全。首先,if判断以及其内存执行代码是非原子性的。 当多线程执行时,可能会同时又多个线程,判断if(instance == null)是否处理,可能多个线程判断成立,那可能就会创建多个实例。

那如何保证线程安全呢?

        相信很多人第一时间都会想到加synchronized关键字,synchronized加载getInstace()函数上确实保证了线程的安全。但是,如果要经常的调用getInstance()方法,不管有没有初始化实例,都会唤醒和阻塞线程。为了避免线程的上下文切换消耗大量时间,如果对象已经实例化了,我们没有必要再使用synchronized加锁,直接返回对象。

public class Singleton {private static Singleton instance = null;private Singleton() {};public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

 这种方式可能会使性能收到影响,因为每次获取实例要加锁。解决思路:我们能不能在第一次创建的时间加锁,后续都不加锁呢。

public class Singleton {private static Singleton instance ;private Singleton(){}public static Singleton getInstance(){if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

 上述方式也称“饿汉式双检锁”。这样就可以保证线程安全,也能保证性能。


 


 

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

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

相关文章

双向dfs,多次dfs

前言&#xff1a;这个答案给我们提供了一种多次dfs的思路&#xff0c;记录queue的size&#xff0c;每次只取size个&#xff0c;就刚刚好只处理了上一次的‘ 题目地址 #include<bits/stdc.h> using namespace std;//定义队列节点 struct node {int x,y; }rear,front; //Q[…

JVM 调优篇2 jvm的内存结构以及堆栈参数设置与查看

一 jvm的内存模型 2.1 jvm内存模型概览 2.2 pc计数器 它是一块很小的内存空间&#xff0c;集合可以忽略不记&#xff0c;也是运行速度最快的存储区域。不会随着程序的运行需要更大的空间。 在jvm规范中&#xff0c;每个线程都有它自己的程序计数器&#xff0c;是线程私有的&…

二、栈和队列-算法总结

文章目录 二、栈和队列2.1 基本应用2.1.1 逆波兰表达式求值2.1.2 有效的括号 2.2 单调栈2.2.1 柱状图中最大的矩形 二、栈和队列 2.1 基本应用 2.1.1 逆波兰表达式求值 150. 逆波兰表达式求值 class Solution {/**思路分析&#xff1a;遇到数则压栈&#xff0c;遇到运算符…

【深度学习】线性回归的从零开始实现与简洁实现

前言 我原本后面打算用李沐老师那本《动手学深度学习》继续“抄书”&#xff0c;他们团队也免费提供了电子版(https://zh-v2.d2l.ai/d2l-zh-pytorch.pdf)。但书里涉及到代码&#xff0c;一方面展示起来不太方便&#xff0c;另一方面我自己也有很多地方看不太懂。 这让我开始思…

Arm GIC-v3中断原理及验证(通过kvm-unit-tests)

一、参考连接 gic-v3相关原理可参考https://zhuanlan.zhihu.com/p/520133301 本文主要通过开源测试工具kvm-unit-tests&#xff0c;针对GIC的中断进行一系列验证&#xff0c;这样可以直入中断底层&#xff0c;熟悉整个原理。 kvm-unit-tests官网为kvm-unit-tests / KVM-Unit…

labview禁用8080端口

需求背景 最近电脑上安装了labview全家桶,发现idea的8080端口项目启动报错,一直提示8080端口被占用。最简单的办法就是找到8080端口的服务,然后关闭这个服务。但是我不想这么做,我想把labview的web服务器的端口给修改了。 操作教程 1、cmd查看8080端口 2、windows进程 同…

022.PL-SQL进阶—分页过程

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

Flask 实现用户登录功能的完整示例:前端与后端整合(附Demo)

目录 前言Demo 前言 对于python用户的登录&#xff0c;以下只是提供一个Demo用于学习 更多的python知识点可从我的专栏中进行学习 python专栏详细分析Flask中的蓝图Blueprint&#xff08;附Demo&#xff09;详细分析Flask部署云服务器&#xff08;图文介绍&#xff09;构建F…

2024 年 GitLab Global DevSecOps 报告解读

近日 GitLab 正式发布了 2024 年 GitLab Global DevSecOps 报告&#xff0c;报告主题为 What’s next in DevSecOps。在全球有超 5000 位 IT 人员参与了该报告的调研&#xff0c;超 70% 为企业管理者&#xff0c;50% 以上的受访者所在企业规模超过 500人。该报告深刻揭示了在 A…

深度学习_GPT2Block详解(casual attention)

一、GTP2Block 整体结构 1.1 block准备 import torch from torch import nn from transformers import GPT2Model, GPT2Config from transformers.models.gpt2.modeling_gpt2 import GPT2Blockcfg GPT2Config() print(cfg.add_cross_attention) blk GPT2Block(cfg, layer_…

《ECMAScript 与 JavaScript:差异与共通》

一、概念辨析 《ECMAScript 与 JavaScript&#xff1a;差异与共通》 ECMAScript&#xff08;简称 ES&#xff09;是一种由 Ecma International 标准化的脚本语言规范。它定义了脚本语言的核心特性&#xff0c;包括语法、类型、语句、关键字等。例如&#xff0c;ECMAScript 规定…

被要求撤回Blackwell?一家初创企业称英伟达侵权自家技术,忍无可忍!英伟达和伙伴微软被齐齐告上法庭,赔偿或高达数十亿!

刚刚&#xff0c;一家初创公司居然把巨头英伟达和微软一起告了&#xff01; 名为Xockets的初创公司在诉讼中称&#xff0c;英伟达和微软公司窃取了其DPU技术&#xff0c;用以开发AI产品&#xff0c;并相互串通以压低其技术的价格&#xff0c;是名副其实的垄断行为&#xff01;…

智汇创想pytest接口自动化测试框架

本测试框架是基于pytest搭建的接口自动化框架&#xff0c;对象为深圳智汇创想官方网站。深圳智汇创想科技有限责任公司&#xff08;深圳智汇创想科技有限责任公司&#xff09;&#xff0c;是一家专注于跨境电子商务的集团公司&#xff0c;全球电商平台多品类多品牌的零售商&…

MATLAB | R2024b更新了哪些好玩的东西?

Hey, 又到了一年两度的MATLAB更新时刻&#xff0c;MATLAB R2024b正式版发布啦&#xff01;&#xff0c;直接来看看有哪些我认为比较有意思的更新吧! 1 小提琴图 天塌了&#xff0c;我这两天才写了个半小提琴图咋画&#xff0c;MATLAB 官方就出了小提琴图绘制方法。 小提琴图…

客户端负载均衡Ribbon实例

文章目录 一&#xff0c;概述二&#xff0c;实现过程三&#xff0c;项目源码1. 源码放送&#xff1a;2. 部署方式 四&#xff0c;功能演示五&#xff0c;其他 一&#xff0c;概述 一般来说&#xff0c;提到负载均衡&#xff0c;大家一般很容易想到浏览器 -> NGINX -> 反…

加密与安全_ sm-crypto 国密算法sm2、sm3和sm4的Java库

文章目录 Presm-crypto如何使用如何引入依赖 sm2获取密钥对加密解密签名验签获取椭圆曲线点 sm3sm4加密解密 Pre 加密与安全_三种方式实现基于国密非对称加密算法的加解密和签名验签 sm-crypto https://github.com/antherd/sm-crypto 国密算法sm2、sm3和sm4的java版。基于js…

PMP--一模--解题--21-30

文章目录 9.资源管理21、 [单选] 项目经理发现一个不可预料的高影响风险已经成为项目的一个因素&#xff0c;团队成员之间的自身利益导致问题得不到解决&#xff0c;项目经理必须快速行动&#xff0c;让团队重新集中精力&#xff0c;以便项目恢复进度&#xff0c;项目经理应该使…

vue3项目实现全局国际化

本文主要梳理vue3项目实现全项目格式化&#xff0c;例如在我前面文章使用若依创建vue3的项目中&#xff0c;地址&#xff1a;若依搭建vue3项目在导航栏中切换&#xff0c;页面中所有的组件的默认语言随之切换&#xff0c;使用的组件库依旧是element-plus&#xff0c;搭配vue-i1…

09-排序1 排序(C)

这一节&#xff0c;测试各类排序算法的运行速度&#xff08;没有基数排序&#xff08;桶&#xff09; 其实在实际学习中&#xff0c;还是有意义的 给定 n 个&#xff08;长整型范围内的&#xff09;整数&#xff0c;要求输出从小到大排序后的结果。 本题旨在测试各种不同的排序…

Windows与Linux下 SDL2的第一个窗口程序

Windows效果和Linux效果如下&#xff1a; 下面是代码&#xff1a; #include <stdio.h> #include "SDL.h"int main(int argc, char* argv[]) { // 初始化SDL视频子系统if (SDL_Init(SDL_INIT_VIDEO) ! 0){// 如果初始化失败&#xff0c;打印错误信息printf(&…