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

设计模式,面试级别的详解(持续更新中)

设计模式,面试级别的详解(持续更新中)

软件的设计原则

常⽤的⾯向对象设计原则包括7个,这些原则并不是孤⽴存在的,它们相互依赖,相互补充

  • 开闭原则(Open Closed Principle,OCP)
  • 单⼀职责原则(Single Responsibility Principle, SRP)
  • ⾥⽒替换原则(Liskov Substitution Principle,LSP)
  • 依赖倒置原则(Dependency Inversion Principle,DIP)
  • 接⼝隔离原则(Interface Segregation Principle,ISP)
  • 合成/聚合复⽤原则(Composite/Aggregate Reuse Principle, C/ARP)
  • 最少知识原则(Least Knowledge Principle,LKP)或者迪⽶特法则 (Law of Demeter,LOD)
    在这里插入图片描述

设计模式的分类

  • 创建型: 在创建对象的同时隐藏创建逻辑,不使用 new 直接实例化对象,程序在判断需要创建哪些对象时更灵活。包括工厂/抽象工厂/单例/建造者/原型模式。
  • 结构型: 通过类和接口间的继承和引用实现创建复杂结构的对象。包括适配器/桥接模式/过滤器/组合/装饰器/外观/享元/代理模式。
  • 行为型: 通过类之间不同通信方式实现不同行为。包括责任链/命名/解释器/迭代器/中介者/备忘录/观察者/状态/策略/模板/访问者模式。

在这里插入图片描述

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。

构造方法必须是私有的、由自己创建一个静态变量存储实例,对外提供一个静态公有方法获取实例

  • 优点
    • 内存中只有一个实例,减少了开销,尤其是频繁创建和销毁实例的情况下并且可以避免对资源的多重占用
  • 缺点
    • 没有抽象层,难以扩展,与单一职责原则冲突。

单例模式的常见写法

饿汉式,线程安全

饿汉式单例模式,顾名思义,类一加载就创建对象,这种方式比较常用,但容易产生垃圾对象,浪费内存空间。

/*** 单例模式。饿汉式* 比较常用,但是容易产生垃圾对象* 优点:不用加锁,执行效率会很高* 缺点:类加载时就初始化,浪费内存*/
public class SingletonEHan {private static SingletonEHan instance = new SingletonEHan();private SingletonEHan(){}public static SingletonEHan getInstance(){return instance;}
}
  • 优点:线程安全,没有加锁,执行效率较高
  • 缺点:不是懒加载,类加载时就初始化,浪费内存空间
    • 懒加载 (lazy loading):使用的时候再创建对象

饿汉式单例是如何保证线程安全的呢

它是基于类加载机制避免了多线程的同步问题,但是如果类被不同的类加载器加载就会创建不同的实例,比如使用反射来破坏单例

懒汉式,线程安全

通过 synchronized 关键字加锁保证线程安全, synchronized 可以添加在方法上面,也可以添加在代码块上面,这里演示添加在方法上面,存在的问题是 每一次调用getInstance获取实例时都需要加锁和释放锁,这样是非常影响性能的。

/*** 单例模式* 懒汉式,线程安全,但是效率很低* 优点:第一次调用才初始化,避免内存浪费* 缺点:必须枷锁synchronized才能保证单例,枷锁会影响效率*/
public class SingletonLanHan{private static SingletonLanHan instance;private SingletonLanHan(){}public static synchronized SingletonLanHan getInstance(){if(instance == null){instance = new SingletonLanHan();}return instance;}
}
  • 优点:懒加载,线程安全
  • 缺点:必须枷锁synchronized才能保证单例,枷锁会影响效率
双重检查锁(DCL, 即 double-checked locking)

采用双锁机制,安全且能在多线程的情况下保持高性能

public class SingletonDCL{private static volatile SingletonDCL instance;private SingletonDCL(){}publica static SingletonDCL getInstance(){if(instance == null){synchronized(SingletonDCL.class){if(instance == null){instance == new SingletonDCL();}}}return instance;}
}
  • 优点:懒加载,线程安全,效率较高
  • 缺点:实现较复杂

这里的双重检查是指两次非空判断,锁指的是 synchronized 加锁。

为什么要进行双重判断

其实很简单,第一重判断,如果实例已经存在,那么就不再需要进行同步操作,而是直接返回这个实例,如果没有创建,才会进入同步块,同步块的目的与之前相同,目的是为了防止有多个线程同时调用时,导致生成多个实例,有了同步块,每次只能有一个线程调用访问同步块内容,当第一个抢到锁的调用获取了实例之后,这个实例就会被创建,之后的所有调用都不会进入同步块,直接在第一重判断就返回了单例。

关于内部的第二重空判断的作用,当多个线程一起到达锁位置时,进行锁竞争,其中一个线程获取锁,如果是第一次进入则为 null,会进行单例对象的创建,完成后释放锁,其他线程获取锁后就会被空判断拦截,直接返回已创建的单例对象。

这里为什么要使用 volatile

volatile的两个特性:可⻅性、禁止指令重排序

这是因为 new 关键字创建对象不是原子操作,创建一个对象会经历下面的步骤:

  1. 在堆内存开辟内存空间
  2. 调用构造方法,初始化对象
  3. 引用变量指向堆内存空间

为了提高性能,编译器和处理器常常会对既定的代码执行顺序进行指令重排序,排序后的顺序可能为1、2、3或者1、3、2,因此当某个线程在乱序运行 1、3、2 指令的时候,引用变量指向堆内存空间,这个对象不为 null,但是没有初始化,其他线程有可能这个时候进入了 getInstance 的第一个 if(instance == null) 判断不为 nulll ,导致错误使用了没有初始化的非 null 实例,这样的话就会出现异常,这个就是著名的DCL 失效问题

,其他线程有可能这个时候进入了 getInstance 的第一个 if(instance == null) 判断不为 nulll ,导致错误使用了没有初始化的非 null 实例,这样的话就会出现异常,这个就是著名的DCL 失效问题**。

⼯⼚模式

简单工厂模式

简单⼯⼚模式指由⼀个⼯⼚对象来创建实例,客户端不需要关注创建逻 辑,只需提供传⼊⼯⼚的参数

UML类图如下:
在这里插入图片描述
适⽤于⼯⼚类负责创建对象较少的情况,缺点是如果要增加新产品,就需要修改⼯⼚类的判断逻辑,违背开闭原则,且产品多的话会使⼯⼚类⽐较复杂。

例子

Calendar 抽象类的 getInstance ⽅法,调⽤createCalendar ⽅法根据不同 的地区参数创建不同的⽇历对象。

Spring 中的 BeanFactory 使⽤简单⼯⼚模式,根据传⼊⼀个唯⼀的标识来 获得 Bean 对象.

⼯⼚⽅法模式

和简单⼯⼚模式中⼯⼚负责⽣产所有产品相⽐,⼯⼚⽅法模式将⽣成具体 产品的任务分发给具体的产品⼯⼚

UML类图如下:
在这里插入图片描述
也就是定义⼀个抽象⼯⼚,其定义了产品的⽣产接⼝,但不负责具体的产品,将⽣产任务交给不同的派⽣类⼯⼚。这样不⽤通过指定类型来创建对象了。

抽象⼯⼚模式

简单⼯⼚模式和⼯⼚⽅法模式不管⼯⼚怎么拆分抽象,都只是针对⼀类产 品,如果要⽣成另⼀种产品,就⽐较难办了!

抽象⼯⼚模式通过在 AbstarctFactory 中增加创建产品的接⼝,并在具体⼦⼯⼚中实现新加产品的创建,当然前提是⼦⼯⼚⽀持⽣产该产品。否则继承的这个接⼝可以什么也不⼲。

UML类图如下:
在这里插入图片描述
从上⾯类图结构中可以清楚的看到如何在⼯⼚⽅法模式中通过增加新产品 接⼝来实现产品的增加的。

相关文章:

设计模式,面试级别的详解(持续更新中)

设计模式,面试级别的详解(持续更新中) 软件的设计原则 常⽤的⾯向对象设计原则包括7个,这些原则并不是孤⽴存在的,它们相互依赖,相互补充。 开闭原则(Open Closed Principle,OCP)单⼀职责原则…...

第9篇:网络访问控制与认证机制

目录 引言 9.1 访问控制策略概述 9.2 认证机制的使用 9.3 密钥分发与证书机制 9.4 访问控制与认证在网络安全中的应用 9.5 网络访问控制与认证的挑战 9.6 总结 第9篇:网络访问控制与认证机制 引言 随着计算机网络的不断普及,安全问题日益受到关…...

CentOS安装NVIDIA驱动、CUDA以及nvidia-container-toolkit

0.提前准备 0.1.更新yum源(以阿里为例) 0.1.1 备份当前的yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 0.1.2 下载新的CentOS-Base.repo 到/etc/yum.repos.d/ CentOS 5 wget -O /etc/yum.repos.d/CentOS-Base…...

STM32调试,发现HAL_Init();之后无法调试,甚至无法让程序停下来

参考文档: STM32调试,发现HAL_Init();之后无法调试,甚至无法让程序停下来 - asml - 博客园 症状 最近开始学习STM32Cube,发现新建工程后无法正常调试,过了HAL_Init();之后就无法继续调试了. 无法进行让程序暂停以及停止等操作.并在输出窗口不断刷出 ERROR: Can n…...

Ajax(web笔记)

文章目录 1.Ajax的概念2.Ajax 的作用3.原生Ajax4.Axios4.1Axios的概念4.2Axios入门 1.Ajax的概念 AsynchronousJavaScriptAndXML,异步的JavaScript和XML 2.Ajax 的作用 数据交换:过Ajax可以给服务器发送请求,并获取服务器响应的数据。异步交互:可以在…...

多入口+vite+vue3预渲染方案

如果你的项目要求加载速度要快,我们如果使用传统的vue3+sfc模式去开发,因为只有一个根节点,空白页面加载出来之后js才回去加载组件渲染,这样页面总是有一个短暂的空白。我们这里不讨论服务器端ssr和预渲染方案,仅仅是为了满足比较极端的优化需求,在这种情况下我的这套方案…...

Vue3+Ts函数封装与应用

目录 一、基础函数 二、实际应用 2.1、根据id找到对应的value值(找第一个) 2.2、根据id找到对应的value值(找所有) 2.3、不重复的升序数组找数字(二分查找) 2.4、重复的无序数组找数字(统计个数) 2.5、将数组整理为树结构(省市区为例) 为什么要积累呢?因为面…...

C语言全局变量和局部变量同时应用的题题型[求一堆数组中10个学生的成绩里最高分、最低分和平均分。]

C语言函数 全局变量与局部结合变量题。 本片代码中包含全局变量max和min。 以及局部变量aver。 全局变量运用于从定义变量开始&#xff0c;局部变量运用于定义它的调用函数内。 正文开始: #include <stdio.h> int max0,min0; int main() { int average(int array[…...

深度学习实战94-基于图卷积神经网络GCN模型的搭建以及在金融领域的场景

大家好,我是微学AI,今天给大家介绍一下深度学习实战94-基于图卷积神经网络GCN模型的搭建以及在金融领域的场景。文章首先介绍了GCN模型的原理及模型结构,随后提供了数据样例,并详细展示了实战代码。通过本文,读者可以深入了解GCN模型在金融场景下的应用,同时掌握代码的具…...

.NET 6新特性 | System.Text.Json功能改进

在.NET 6.0中&#xff0c;JSON处理库得到了显著的改进&#xff0c;主要体现在System.Text.Json上。以下是对.NET 6.0中改进的JSON处理库的详细分析&#xff1a; 一、System.Text.Json的引入与优势 在.NET 6中&#xff0c;Microsoft引入了新的JSON库System.Text.Json作为官方推…...

Matlab如何对全局优化算法启动并行计算

在 MATLAB 中&#xff0c;启用并行计算可以显著提高一些优化算法&#xff08;如遗传算法 ga 和粒子群算法 particleswarm&#xff09;的速度&#xff0c;特别是在种群或粒子群较大时。要启用并行计算&#xff0c;可以使用 UseParallel 参数。 1. 启用并行计算步骤 Step 1: 检…...

MYSQL-查看数据库中的存储过程语法(六)

13.7.5.9 SHOW CREATE PROCEDURE 语句 SHOW CREATE PROCEDURE proc_name此语句是 MySQL 扩展。它返回确切的字符串 &#xff0c;可用于重新创建命名的存储过程。SHOW CREATE FUNCTION&#xff0c;显示有关存储函数的信息 &#xff08;参见第 13.7.5.8 节“ SHOW CREATE FUNCTI…...

【深度学习】(12)--模型部署 <连接客户端与服务端>

文章目录 模型部署一、模型部署的定义与目的二、模型部署的步骤三、模型部署的方式四、Flask框架五、实现模型部署1. 搭建服务端1.1 初始化Flask app1.2 加载模型1.3 数据预处理1.4 构建装饰器1.5 完整代码 2. 搭建客户端2.1 服务端网址2.2 发送请求2.3 完整代码 六、运行使用 …...

优化SQL查询的最佳实践:提升数据库性能的关键

SQL 查询是数据库操作的核心&#xff0c;特别是当数据量庞大时&#xff0c;性能问题尤为明显。优化 SQL 查询不仅能减少响应时间&#xff0c;还能提高系统整体的可伸缩性。本文将从索引、查询结构、数据库设计和缓存等方面详细介绍如何优化 SQL 查询以提升性能。 一、索引的使…...

【AIGC视频生成】视频扩散模型(综述+最新进展)

文章目录 一、综述1.1 扩散模型1.1.1 Denoising Diffusion Probabilistic Models (DDPMs)1.1.2 Score-Based Generative Models (SGMs)1.1.3 Stochastic Differential Equations (Score SDEs) 1.2 相关任务1.3 数据集1.4 评价指标 二、年度进展1.runway gen2.1 Gen-1&#xff1…...

如何下载3GPP协议?

一、进入3GPP网页 https://www.3gpp.org/ 二、点击“Specifications &Technologies” 三、点击“FTP Server” 网址&#xff1a; https://www.3gpp.org/specifications-technologies 四、找到“latest”&#xff0c;查看最新版 网址&#xff1a; https://www.3gpp.org/ftp…...

目标检测系统操作说明【用户使用指南】(python+pyside6界面+系统源码+可训练的数据集+也完成的训练模型)

1.100多种【基于YOLOv8/v10/v11的目标检测系统】目录&#xff08;pythonpyside6界面系统源码可训练的数据集也完成的训练模型&#xff09; 2.目标检测系统【环境搭建过程】&#xff08;GPU版本&#xff09; 3.目标检测系统【环境详细配置过程】&#xff08;CPU版本&#xff0…...

Vue中使用路由

目录 单页应用程序&#xff1a;SPA - Single Page Application路由 VueRouterVueRouter使用步骤组件存放目录问题 路由模块封装声明式导航 - 导航连接两个类名自定义匹配类名 声明式导航 - 跳转传参Vue路由 - 重定向Vue路由 - 404Vue路由 - 模式设置 编程式导航 - 基本跳转编程…...

【Linux】多线程安全之道:互斥、加锁技术与底层原理

目录 1.线程的互斥 1.1.进程线程间的互斥相关背景概念 1.2.互斥量mutex的基本概念 所以多线程之间为什么要有互斥&#xff1f; 为什么抢票会抢到负数&#xff0c;无法获得正确结果&#xff1f; 为什么--操作不是原子性的呢&#xff1f; 解决方式&#xff1a; 2.三种加锁…...

收藏多年的四款音频剪辑工具你pick哪一个?

在这个时代&#xff0c;音频剪辑已经成为音乐制作、播客、自媒体等领域的必备技能。而随着网络技术的飞速发展&#xff0c;我们不再需要安装庞大的软件&#xff0c;只需一个浏览器&#xff0c;就能轻松完成音频剪辑工作。今天&#xff0c;就让我为大家推荐几款优秀的在线音频剪…...

WSABuilds:3种架构适配+5分钟部署,打造Windows安卓开发与运行环境

WSABuilds&#xff1a;3种架构适配5分钟部署&#xff0c;打造Windows安卓开发与运行环境 【免费下载链接】WSABuilds Run Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/or Magisk …...

Python爬虫入门:10步快速掌握网页数据抓取,【大数据实战】如何从0到1构建用户画像系统(案例+数据仓库+Airflow调度)。

准备工作 安装Python环境&#xff0c;确保版本在3.6以上。推荐使用Anaconda管理Python环境&#xff0c;避免版本冲突。安装必要的库&#xff0c;如requests、BeautifulSoup、lxml等。可以通过pip命令快速安装&#xff1a; pip install requests beautifulsoup4 lxml理解基本概念…...

TurboDiffusion保姆级教程:基于Wan2.1/Wan2.2的AI视频生成快速上手

TurboDiffusion保姆级教程&#xff1a;基于Wan2.1/Wan2.2的AI视频生成快速上手 1. 引言 1.1 为什么选择TurboDiffusion 想象一下&#xff0c;你只需要输入一段文字描述&#xff0c;就能在几秒钟内生成一段高质量的视频。这不是科幻电影里的场景&#xff0c;而是TurboDiffusi…...

008.S3C2440中断分析|千篇笔记实现嵌入式全栈/裸机篇

1. 流程 S3C2440中断流程如下&#xff0c; 发生中断时&#xff0c;[SUB]SRCPND源挂起寄存器对应的bit位会置位&#xff0c; 然后[SUB]MASK屏蔽寄存器对应的bit位会卡一下&#xff0c;决定中断流要不要继续&#xff0c; 也就是说不管中断有没有被屏蔽&#xff0c;源挂起寄存…...

RMBG-2.0镜像安全加固:非root用户运行、网络隔离、资源限制配置指南

RMBG-2.2镜像安全加固&#xff1a;非root用户运行、网络隔离、资源限制配置指南 在AI应用快速部署的今天&#xff0c;我们往往更关注模型的效果和速度&#xff0c;而忽略了运行环境的安全性。想象一下&#xff0c;你精心部署了一个图像处理服务&#xff0c;结果因为一个简单的…...

用快马AI快速生成你的第一个微信小程序待办事项原型

用快马AI快速生成你的第一个微信小程序待办事项原型 最近想尝试开发一个微信小程序来管理日常任务&#xff0c;但作为新手&#xff0c;从零开始写代码确实有点无从下手。好在发现了InsCode(快马)平台&#xff0c;它通过AI生成代码的能力&#xff0c;帮我快速搭建了一个待办事项…...

Topeka Android应用终极部署指南:从源码编译到多渠道分发的完整教程

Topeka Android应用终极部署指南&#xff1a;从源码编译到多渠道分发的完整教程 【免费下载链接】topeka A fun to play quiz that showcases material design on Android 项目地址: https://gitcode.com/gh_mirrors/to/topeka Topeka是一款基于Material Design设计理念…...

C#运动控制入门:从零开始用PID算法控制伺服电机(附完整代码)

C#运动控制入门&#xff1a;从零开始用PID算法控制伺服电机&#xff08;附完整代码&#xff09; 第一次尝试用代码控制伺服电机时&#xff0c;我盯着那台嗡嗡作响的设备&#xff0c;看着它时而抽搐、时而狂奔&#xff0c;完全不像预期那样优雅地移动到指定位置。那一刻我意识到…...

从特斯拉到5G基站:Clarity 3D Solver在汽车电子设计中的7个隐藏技巧

从特斯拉到5G基站&#xff1a;Clarity 3D Solver在汽车电子设计中的7个隐藏技巧 当112Gbps高速互连成为5G基站标配&#xff0c;当自动驾驶汽车的雷达系统需要处理毫米波频段的复杂干扰&#xff0c;电磁兼容性&#xff08;EMC&#xff09;工程师们正面临前所未有的挑战。传统仿真…...

OpenClaw小团队协作:Kimi-VL-A3B-Thinking共享模型的经济部署

OpenClaw小团队协作&#xff1a;Kimi-VL-A3B-Thinking共享模型的经济部署 1. 为什么我们需要共享模型部署&#xff1f; 去年夏天&#xff0c;我们团队在开发一个多模态内容分析工具时&#xff0c;遇到了一个典型的技术困境&#xff1a;每个成员都需要频繁调用Kimi-VL-A3B-Thi…...