java八股——常见设计模式
上一篇传送门:点我
有哪些设计模式?
按照模式的应用目标分类,可以分为创建型模式、结构型模式、行为型模式三类。
创建型模式:
对象实例化的模式,创建型模式用于解耦对象的实例化过程。
单例模式:某个类只能有一个实例,提供一个全局的访问点。
工厂方法模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
抽象工厂模式:创建相关或依赖对象的家族,而无需明确指定具体类。
创建者模式:封装一个复杂对象的创建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
结构型模式:
把类或对象结合在一起形成一个更大的结构。
装饰器模式:动态的给对象添加新的功能。
代理模式:为其它对象提供一个代理以便控制这个对象的访问。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
享元模式:通过共享技术来有效的支持大量细粒度的对象。
行为型模式:
类和对象如何交互,及划分责任和算法。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
模板方法模式:定义一个算法结构,而将一些步骤延迟到子类实现。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
观察者模式:对象间的一对多的依赖关系。
仲裁者模式:用一个中介对象来封装一系列的对象交互。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
建造者模式:允许一个对象在其对象内部状态改变时改变它的行为。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。
说说设计模式的基本原则
1.单一职责原则:对于一个类,只有一个引起该类变化的原因;该类的职责是唯一的,且这个职责是唯一引起其他类变化的原因;
2.里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能;
3.依赖倒置原则:程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合;
4.接口隔离:客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上;
5.迪米特原则:迪米特法则又叫做最少知识原则,就是说一个对象应当对其它对象又尽可能少的了解,不和陌生人说话;
6.开闭原则:对扩展开放,对修改关闭;
7.合成复用原则:在软件复用时,要尽量优先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
单例模式
什么是单例模式?
单例模式是一种创建型设计模式,它必须保证单例对象的类仅有一个实例,并提供一个访问它的全局访问点。这个模式主要应用于那些只需要一个对象来协调整个系统运作的场景。通过确保类只有一个实例,我们可以节省系统资源,因为不需要为多次创建和销毁对象分配内存。同时,单例模式也有助于确保数据的一致性,因为所有的请求都通过同一个实例来处理。
单例模式如何实现?
单例模式常见的实现方法有以下几种:
1.饿汉式:在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。它是线程安全的实现方式。
public class Singleton { // 在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快 private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; }
}
2.懒汉式:在第一次调用时初始化,这是懒加载的思想。但是这种方式在多线程环境下是不安全的。由于懒汉式在获取单例对象时,会先判断当前是否已经存在对象实例,而如果同一时刻有两个甚至更多线程去进行判断,则可能会创建出多个单例对象。因此不做任何处理的懒汉式创建单例对象是非线程安全的。
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { //调用时若还没有对单例对象初始化,则new一个对象(线程不安全)if (instance == null) { instance = new Singleton(); } return instance; }
}
3.优化后的懒汉式:由于一般的懒汉式会有线程不安全的问题,所以可以考虑给代码加synchronized锁,从而避免线程安全问题的出现。
可以在getInstance()方法上添加synchronized关键字,从而保证线程安全。
public class Singleton { private static Singleton instance; private Singleton() {} //方法加锁保证线程安全public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
}
以上方法虽然保证了线程安全,但是每次调用getInstance()都需要进行同步,由于只有第一次调用时才会创建单例对象,因此这会造成大量不必要的同步开销。另一方面,由于在JVM内部会存在指令重排序(JVM在保证最终结果正确的情况下,可以不按照程序编码的顺序执行语句,尽可能提高程序的性能)的情况出现,这在并发场景下,有可能会出现NullPointerException空指针异常。
PS:指令重排可参考:我给面试官讲解了单例模式后,他对我竖起了大拇指!
因此可以设置双重校验锁,并结合volatile关键字,从而在保证线程安全的同时减少不必要的开销,也避免了指令重排问题的出现。
public class Singleton {private volatile static Singleton instance; // 使用volatile防止JVM指令重排private Singleton() {}public static Singleton getInstance() {if (instance == null) {//对代码块中的类对象加锁synchronized(Singleton.class){if(instance == null){instance = new Singleton();}}}return instance;}
}
4.静态内部类:静态内部类同样实现了懒加载,而且保证了线程安全。这种方式是Singleton模式的最佳实现之一。
public class Singleton { private Singleton() {} //定义静态内部类private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; }
}
5.枚举实现单例(最优!!!):枚举法实现单例与上述其他方法相比,代码更加地简洁,并且不需要做任何额外的操作去保证对象单一性与线程安全性,最最重要的是,它能防止反射、序列化与反序列化强制生成多个实例对象从而使得单例模式被破坏。
反射破坏单例的原理: 通过java反射中的setAccessible(true)能够强制访问类的私有构造器(将private权限强制转为public),从而可以调用构造器创建新的对象。
序列化与反序列化破坏单例的原理: 当使用readObject() 方法读入对象时,它必定会返回一个新的对象实例,必然指向新的内存地址。
public enum Singleton { INSTANCE; // 可以在这里定义其他方法 public void doSomething() { // ... }
}
工厂模式
什么是工厂模式?
工厂模式是一种用于创建对象的设计模式,它通过将对象的创建逻辑与使用逻辑分离,从而提高了代码的可维护性和可扩展性。在工厂模式中,我们定义一个抽象的工厂接口,用于声明创建对象的方法,然后创建具体的工厂类来实现这个接口。这些具体的工厂类负责根据特定的需求创建相应的对象。通过这种方式,我们可以灵活地管理和扩展对象的创建过程,而无需修改客户端代码。
工厂模式有哪几种,它们的区别是什么?
工厂模式主要有三种:简单工厂模式、工厂方法模式和抽象工厂模式。
1.简单工厂模式(静态工厂模式): 这是最简单的工厂模式,但它不属于GOF23种设计模式中的其中一种,它通过一个工厂类来负责创建其他类的实例。客户端只需要传入相应的参数,工厂类就会根据这些参数来返回对应的产品实例。这种模式的优点是实现了客户端与具体产品类的解耦,客户端无需关心产品的具体创建过程。然而,缺点是当需要增加新的产品时,需要修改工厂类的代码,这违背了开闭原则。
工厂方法模式: 工厂方法模式进一步抽象了对象的创建过程。它定义了一个创建对象的接口,让子类来决定具体实例化哪一个类。这样,客户端只需要关心所需产品对应的工厂,而无需了解具体的创建细节。这种模式的优点是在增加新产品时,只需要增加相应的工厂子类,而无需修改原有的代码,这符合开闭原则。但缺点是增加了系统的复杂度,因为需要编写更多的工厂子类。
抽象工厂模式: 抽象工厂模式提供了一种方式来创建一系列相关或相互依赖的对象,而不需要指定它们具体的类。它定义了一个接口,用于创建相关产品族的多个产品对象。客户端只需要知道产品的抽象类型或接口类型,而无需关心具体实现。这种模式的优点是能够隔离产品代码,提高系统的可扩展性和可维护性。然而,当产品族中需要增加一个新的产品时,需要修改抽象工厂的接口以及所有实现了该接口的工厂类,这同样会增加系统的复杂度和理解难度。
JDK中的常用设计模式有哪些?
1.单例模式:确保一个类只有一个实例,并提供一个全局访问点。
JDK体现:Runtime类
2.工厂模式:工厂模式用于创建对象,它提供了一种封装机制来减少程序之间的耦合性。
JDK体现:Integer.valueOf(),Class.forName()
3.原型模式:拷贝原型来创建新的对象,拷贝是比new更快的创建对象的方法,
当需要大批量创建新对象而且都是同一类的对象的时候考虑使用原型模式。
JDK体现:clone()
4.代理模式:为其他对象提供一种代理以控制对这个对象的访问。
JDK实现:动态代理
5.迭代器模式:将集合的迭代和集合本身分离。
JDK实现:Iterator迭代器
6.适配器模式:将一个类的接口转换成客户端所期望的另一个接口形式。
JDK实现:InputStream、OutputStream
7.策略模式:定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。
JDK实现:JUC中线程池的拒绝策略
Spring中的常用设计模式有哪些?
1.单例模式: 在Spring中,Bean的默认作用域就是单例。这意味着在整个应用程序中只有一个Bean实例,由Spring容器负责管理。这种机制可以节省资源并提高性能。
2.工厂模式:Spring中的BeanFactory和ApplicationContext就是工厂模式的应用。它们负责创建和管理Bean,隐藏了具体实例化的细节,使得应用程序更易于扩展和维护。
3.代理模式:Spring AOP中广泛使用了代理模式。通过代理对象来实现对目标对象的增强,如日志记录、事务管理等。Spring支持JDK动态代理和CGLIB代理。
4.观察者模式:Spring中的事件机制就是观察者模式的应用。当某个事件发生时,相关的监听器会接收到通知并执行相应的操作。
5.模板方法模式:在Spring的RedisTemplate等模板类中使用了模板方法模式。它定义了一组通用的操作方法,同时允许子类根据需要自定义某些步骤的具体实现。
6.适配器模式:Spring中的适配器模式应用比较广泛,如HandlerAdapter、ViewResolver等。它们都是通过适配器来实现不同组件之间的兼容。
下一篇传送门: 点我
相关文章:
java八股——常见设计模式
上一篇传送门:点我 有哪些设计模式? 按照模式的应用目标分类,可以分为创建型模式、结构型模式、行为型模式三类。 创建型模式: 对象实例化的模式,创建型模式用于解耦对象的实例化过程。 单例模式:某个类…...
机器学习 - metric评估方法
有一些方法来评估classification model。 Metric name / Evaluation methodDefinitionCodeAccuracyOut of 100 predictions, how many does your model get correct? E.g. 95% accuracy means it gets 95/100 predictions correct.torchmetrics.Accuracy() or sklearn.metric…...
书生·浦语大模型趣味Demo作业( 第二节课)第二期
文章目录 基础作业进阶作业 基础作业 进阶作业 熟悉 huggingface 下载功能,使用 huggingface_hub python 包,下载 InternLM2-Chat-7B 的 config.json 文件到本地(需截图下载过程) 完成 浦语灵笔2 的 图文创作 及 视觉问答 部署&…...
VScode使用持续更新中。。。
VScode 安装 Ubuntu18.04安装和使用VScode 使用 Vscode如何设置成中文...
YUM仓库和编译安装
目录 一.YUM仓库搭建 1.简介: 2.搭建思路: 3.实验:单机yum的创建 二.编译安装 1.简介 2.安装过程 3.实验:编译安装nginx 一.YUM仓库搭建 1.简介: yum是一个基于RPM包(是Red-Hat Package Manager红…...
IPv4子网判断
有时候,服务后端需要对客户端的所属组进行判断,以决定何种访问策略权限。而客户端IP所在子网是一种很简单易实现的分组方法。 虽然现在早已经进入IPv6时代,不过IPv4在局域网仍广泛使用,它的定义规则相对简单,本文介绍的…...
CSS 实现航班起飞、飞行和降落动画
CSS 实现航班起飞、飞行和降落动画 效果展示 航班起飞阶段 航班飞行阶段 航班降落 CSS 知识点 animation 属性的综合运用:active 属性的运营 动画分解 航班滑行阶段动画 实现航班的滑行阶段动画,需要使用两个核心物件,一个是跑动动画&#x…...
设计模式——建造者模式03
工厂模式注重直接生产一个对象,而建造者模式 注重一个复杂对象是如何组成的(过程),在生产每个组件时,满足单一原则,实现了业务拆分。 设计模式,一定要敲代码理解 组件抽象 public interface …...
【机器学习】《机器学习算法竞赛实战》思考练习(更新中……)
文章目录 第2章 问题建模(一)对于多分类问题,可否将其看作回归问题进行处理,对类别标签又有什么要求?(二)目前给出的都是已有的评价指标,那么这些评价指标(分类指标和回归…...
机场数据治理系列介绍(5)民用机场智慧能源系统评价体系设计
目录 一、背景 二、体系设计 1、评价体系设计维度 2、评价体系相关约定 3、评价指标体系框架设计 4、能源利用评价指标 5、环境友好评价指标 6、智慧管控评价指标 7、安全保障评价指标 三、具体落地措施 一、背景 在“双碳”国策之下,各类机场将能源系统建…...
[LeetCode][LCR190]加密运算——全加器的实现
题目 LCR 190. 加密运算 计算机安全专家正在开发一款高度安全的加密通信软件,需要在进行数据传输时对数据进行加密和解密操作。假定 dataA 和 dataB 分别为随机抽样的两次通信的数据量: 正数为发送量负数为接受量0 为数据遗失 请不使用四则运算符的情况…...
Linux: linux常见操作指令
目录 01.ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令(重要) 06.rmdir指令 && rm 指令(重要) 07.man指令(重要) 07.cp指令(重要) 08.mv指令&#…...
【BPNN】BP神经网络代码
主代码 %function main() clc clear close all %% 1.原始数据 %输入 SR1[20.55 22.44 25.37 27.13 29.45 30.10 30.96 34.06 36.42 38.09 39.13 39.99 ...41.93 44.59 47.30 52.89 55.73 56.76 59.17 60.63]; SR2[0.6 0.75 0.85 0.9 1.05 1.35 1.45 1.6 1.7 1.85 2.15 2.2 2.2…...
基于mqtt的物联网控制移动应用程序开发
具体实现问题 MQTT模型、特点、服务质量、报文、消息类型表 java实现mqtt两种方式:Paho Java原生库、spring boot MQTT与HTTP:哪一个最适合物联网? mqtt协议和http协议区别 应用是如何实现mqtt协议 通过调用安卓的MQTT库来实现MQTT协议&…...
MPLS-基础、LSR、LSP、标签、体系结构
MPLS技术 MPLS基础 MPLS:转发数据时,只在网络边缘分析IP报文头,不在每一跳都分析,节约了转发时间。 MPLS:Multiprotocol Label Switching,多协议标签交换骨干网技术。主要应用:VPN、流量工程…...
【RV1126】Ubuntu22.04下sdk编译问题汇集
对于新版本Ubuntu系统来编译SDK,尤其是buildroot ,是一个巨大考验,发现问题如下: 1. c-stack.c的SIGSTKSZ错误 buildroot 报错:c-stack.c:55:26:error:missing binary operator before token “(“55 在buildroot目录中找到c-s…...
51单片机使用uart串口和助手简单调试
基础知识 参考 特殊功能寄存器PCON(控制波特率是否加倍SMOD)、TMOD(T0,T1计时器的功能方式)、TCON(T0,T1计时器的控制)、串口中断、SCON(串口数据控制寄存器) 关闭定时器1中断&…...
Python网络爬虫(五):b站弹幕
上一篇对b站的视频评论爬取进行了探讨,这一篇是弹幕。直接上代码: import csv import json import re import chardet import requestsheaders = {user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Saf…...
Docker环境安装Postgresql数据库Posrgresql 15.6
宿主机是ubuntu 22.04版本 ubuntu宿主机上安装docker,参见官方文档https://docs.docker.com/engine/install/ubuntu/, docker-ce是社区版 docker-ee是企业版 1、检查Docker是否安装 rootODS1SPGOFSDEV:~# docker Command docker not found, but can be installed …...
当代软件专业大学生与青年在新质生产力背景下的发展探究
在新质生产力的浪潮中,信息技术以前所未有的速度革新,为软件专业的大学生和青年带来了丰富的机遇,同时也伴随着一系列的挑战。他们如何把握时代的脉搏,实现个人的发展,成为了值得深入探讨的话题。 一、新质生产力背景下的机遇 随着新质生产力的不断发展,信息技术在各个领…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
