常见的设计模式(超详细)

news2024/9/28 11:21:01

文章目录

  • 单例模式
    • 饿汉式单例模式
    • 懒汉式单例模式
    • 双重检索单例模式
  • 工厂模式
    • 简单工厂模式
    • 工厂(方法)模式
    • 抽象工厂模式
  • 原型模式
  • 代理模式

单例模式

确保一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。

饿汉式单例模式

饿汉式单例模式在类加载的时候完成了实例化,因为我们将构造函数设为了私有,所有其他的对象不能通过new类创建这个类的实例,然后提供了一个公共的静态方法返回这个类的唯一实例。因为只有一个实例化对象,所以不存在线程安全问题,在平时不能通过new进行对象的创建,只能通过给定的那个全局访问点通过类名进行调用

在这里插入图片描述

/**
 * 饿汉式单例模式
 */
public class SingletonPattern {

    // 在类加载时完成了实例化
    private static SingletonPattern singletonPattern = new SingletonPattern();

    // 私有化构造函数,防止其他对象使用new创建该类的对象
    private SingletonPattern() {
    }

    // 提供一个公共的静态方法,返回该类的唯一实例
    public static SingletonPattern getSingletonPattern() {
        return singletonPattern;
    }
}



懒汉式单例模式

懒汉式单例在类加载的时候不创建对象,在第一次使用的时候进行创建,这样创建的优点是如果该单例对象在系统中没有被使用,那么就不会造成资源的浪费。但是懒汉式单例会出现线程安全问题,当多线程访问时,有可能出现多个线程同时if,就会创建出多个对象。

在这里插入图片描述

/**
 * 懒汉式单例模式
 */
public class SingletonPattern1 {

    // 初始化一个null对象
    private static volatile SingletonPattern1 singletonPattern = null;

    // 私有化构造函数,防止别的对象使用new创建该类的对象
    private SingletonPattern1() {
    }

    // 提供一个公共的静态方法,返回该类的唯一实例
    public static SingletonPattern1 getSingletonPattern() {
        if (singletonPattern == null) {
            singletonPattern = new SingletonPattern1();
        }
        return singletonPattern;
    }
}

要解决这个线程安全的问题可以有两种方式,第一种是给方法加锁,但是给方法加锁之后一次只能获取到一个线程,效率较低。第二种是给代码块加锁,需要使用双重检索
在这里插入图片描述

双重检索单例模式

既提高了效率,又提高了安全性,使用双重if的原因是,当只有一个if时,如果锁加载if代码块的外面,这时候和加载方法上是一样的,效率低;如果加在if内,这是后如果并发量大,几个线程同时进行if然后进入if,虽然内部代码被锁包裹,但是已经进入的线程一个接一个执行,仍然会创建出多个对象,此时需要给内部代码块再加一层if,这时候即提高了效率,又提高了安全性。

/**
 * 双重检索单例模式
 */
public class SingletonPattern2 {

    // 初始化一个null对象
    private static SingletonPattern2 singletonPattern = null;

    // 私有化构造函数,防止别的对象使用new创建该类的对象
    private SingletonPattern2() {
    }

    // 提供一个公共的静态方法,返回该类的唯一实例
    public static SingletonPattern2 getSingletonPattern() {
        if (singletonPattern == null) {
            synchronized (SingletonPattern2.class) {
                if (singletonPattern == null) {
                    singletonPattern = new SingletonPattern2();
                }
            }
        }
        return singletonPattern;
    }
}


此时问题并没有完全解决,我们知道一个对象创建的过程主要分为三步,分配内存,初始化对象,指向刚分配的地址,但是第二步和第三步由于CPU的优化,可能会产生排序,我们一般认为执行顺序为123,但是可能会先执行3再执行2,这时候的对象是一个半成品对象,但是也不是null所以此时的情况并没有完全解决,需要添加volatile,只有当所有步骤都执行完之后才会将对象的地址传给引用参数。

在这里插入图片描述

工厂模式

简单工厂模式

简单工厂模式又称为静态工厂方法模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责其他类的实例,被创建的实例通常都具有共同的父类。优点是实现对象的创建和使用分离,创建完全交给专门的工厂类去负责,程序员不关心怎么创建,只关心怎么使用。缺点是工厂类不够灵活,如果新增一个产品就要修改工厂类,就要修改它的判断逻辑,如果产品很多的话,这个逻辑就会非常复杂。比如就是一台咖啡机可以理解为一个工厂模式,你只需要按下想喝的咖啡品类的按钮,他就会给你生产一杯相应的咖啡,你不需要管他的内部具体实现,只需要告诉它你的需求。

在这里插入图片描述

工厂(方法)模式

简单工厂模式当有新产品加入时必须要修改工厂类,需要在其中加入必要的业务逻辑,这违反了开闭原则,没有办法做到灵活扩展。工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化那个类。工厂方法使一个类的实例化延迟到其子类。

在这里插入图片描述

在这里插入图片描述

在工厂模式中,之前的核心工厂变成了一个抽象接口,负责给出工厂应该实现的方法,它不在负责所有产品的创建,将具体产品的创建交给子类去做,这样就诞生了具体的子工厂,子工厂即子类,负责生成具体的产品对象,这样做可以将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类,在现在的工厂模式中,如果需要新增一个产品,不需要修改原有的工厂类逻辑,但是需要新增一个工厂,这样看起来比较复杂,但是在面向对象语言中,需要遵循开闭原则,就是程序对于扩展是开放的,对于修改时封闭的

在这里插入图片描述

Collection就是一个常见的工厂方法模式,其中Collection就是抽象工厂,具体工厂时LinkedList和ArrayList,抽象产品就是Iterator,具体产品就是ListItr和Itr。

抽象工厂模式

在这里插入图片描述

抽象工厂模式可以使具体工厂类,可以创建多个大类对象,但是还需要修改抽象工厂和具体工厂的代码,违反开闭原则。

原型模式

原型模式属于创建型模式,用来创建一个已有的对象的完全相同的复制品。这个时候如果直接复制的话,需要创建一个相同类的对象,然后遍历原始对象的所有成员变量以及所有属性,然后将这些变量的值复制到新的对象中,但是这个对象的某些成员变量是私有的,不对外公开,或没有提供访问器,那么外部是没有办法去复制的,并且对象实现的某个接口传给我们时,我么你只知道它的某个接口的实现类,他具体的类是哪一个,这是不知道的。那么原型模式就是去解决复制对象的问题的,原型模式将这个复制过程称之为克隆,原型模式就是将这个克隆的过程委派给被克隆的实际对象,由这个被克隆的对象自己去负责克隆,原型模式为所有被克隆的对象提供了一个通用接口,原型对象需要克隆的话就去实现这个接口(clone),就在克隆方法中去实现自己的克隆逻辑。

代理模式

代理模式就是为其他对象提供一种代以控制这个对象的访问。例:黄牛买票,婚介

代理模式分为静态代理和动态代理,动态代理又分为JDK代理和CGLIB动态代理

优点是代理模式能够协调调用者和被调者,在一定程度上降低系统的耦合度,并且可以灵活的隐藏被代理对象的部分功能和服务,也增加了额外的功能和服务,缺点就是使用代理模式程序没有直接调用性能高,并且使用代理模式提高了代码的复杂度。

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

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

相关文章

读书笔记-《ON JAVA 中文版》-摘要21第十九章 类型信息-2]

文章目录 第十九章 类型信息7. 动态代理8. Optional类9. 接口和类型10. 本章小结 第十九章 类型信息 7. 动态代理 代理是基本的设计模式之一。一个对象封装真实对象,代替其提供其他或不同的操作—这些操作通常涉及到与“真实”对象的通信,因此代理通常…

Shell脚本学习-for循环结构4

案例1: 批量创建10个系统账号chang01~chang10,并设置密码(密码不能相同)。(密码随机8位字符) 脚本: #!/bin/bashfor i in seq -w 10 douseradd chang$i &&\echo "root$i" …

网络——初识网络

网络基础 文章目录 网络基础计算机网络产生的背景认识网络协议网络协议初识协议分层OSI七层模型TCP/IP四层模型网络传输基本流程协议报头 认识IP地址认识MAC地址ifconfig查看主机地址ifconfig查看主机地址 计算机网络产生的背景 独立模式:计算机之间相互独立 早期的…

Windows安装JDK和JRE的方法

原文网址:Windows安装JDK和JRE的方法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows安装JDK和JRE(Java8)的方法。 下载 下载入口:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html jdk-8…

docker compose一键部署lnmt环境

创建docker compose 目录 [rootlocalhost ~]# mkdir -p /compose_lnmt 编写nginx的dockerfile文件 创建目录 [rootlocalhost compose_lnmt]# mkdir -p nginx 编写nginx配置文件 [rootlocalhost nginx]# vim nginx.conf user root; #运行身份#nginx自动设置进程…

socket server服务器开发常见的并发模型

两种高效的事件处理模式 服务器程序通常需要处理三类事件:I/O 事件、信号及定时事件。有两种高效的事件处理模式:Reactor和 Proactor,同步 I/O 模型通常用于实现Reactor 模式,异步 I/O 模型通常用于实现 Proactor 模式。 无论是 …

MySQL正则表达式检索数据

目录 一、使用正则表达式进行基本字符匹配 1.使用regexp关键字 2.使用正则表达式 . 二、进行OR匹配 1.为搜索两个串之一,使用 | 2.匹配几个字符之一[] 3.匹配范围 4.匹配特殊字符 过滤数据允许使用匹配、比较、通配符操作来寻找数据,但是随…

Maven依赖爆红的几种解决思路

说明:本文介绍Maven依赖爆红,排查错误的几种思路; 思路一:删除本地仓库.lastupdate文件; 找到本地maven仓库,全局搜索.lastupdate文件,把搜索出来的文件全部删除。.lastupdate后缀名的文件&am…

基础实验篇 | uORB消息读写与自定义实验(二)

导读 uORB是PX4/Pixhawk系统中非常重要且关键的模块之一,是用于无人机模块间通信的协议机制。本篇将详细介绍uORB并详细拆解uORB消息读写与自定义实验全流程(二)。 基础实验篇 | uORB消息读写与自定义实验(二) 01 RflySim平台的uORB消息读写…

分析Python招聘数据,可视化展示招聘信息详情

前言 一. 数据来源分析 1. 明确需求 明确采集网站以及数据内容 数据: 职位信息 网址: https://we.51job.com/pc/search?keywordpython&searchType3&sortType0&metro2. 抓包分析 通过开发者工具进行抓包分析 I. 打开开发者工具: F12 / 右键点击检查选择networ…

Windows下JDK安装与环境变量配置

文章目录 每日一句正能量前言安装步骤配置环境变量验证环境变量是否配置成功后记 每日一句正能量 生命,就像一场永无休止的苦役,不要惧怕和拒绝困苦,超越困苦,就是生活的强者。任何经历都是一种累积,累积的越多,人就越成熟;经历的越多,生命就越有厚度。 本来不想写JDK的安装的&…

基于LLM的SQL应用程序开发实战(二)

基于LLM的SQL应用程序开发实战(二) 16.2 使用LangChain SQL代理 回到案例应用本身,我们使用“Run All”的方式重新运行一下,让大家看见更多内部的内容,如图16-5所示,因为在VSCode代码编辑器中,可以看见Jupyter关于当前应用的变量(variable)。 图16- 5 查询Jupyter V…

新版发布 | Cloudpods v3.10.4 和 v3.9.12 正式发布

Cloudpods v3.10.4 功能优化 【主机】支持 PVE 资源的生命周期管理 【费用】优化阿里云账单资源类型名称(企业版) 【主机】选择 VMware 平台镜像,磁盘支持容量变更 【主机】在线修改密码需先探测 QGA 状态 【主机】热迁移取消”快速收敛…

【ARM64 常见汇编指令学习 13 -- ARM 汇编 ORG 伪指令学习】

文章目录 ARM ORG 指令介绍UEFI 中对 ORG 指令的使用 ARM ORG 指令介绍 在ARM汇编中,"org"是一个汇编器伪指令,用于设置下一条指令的装入地址。"org"后面跟着的是一个表达式,这个表达式的值就是下一条指令的装入地址。如…

基于STM32设计的智能空调

一、项目背景 随着人们生活水平的不断提高,对居住环境的舒适度要求也越来越高。空调作为一种重要的家电设备,已经成为了现代家庭中必不可少的一部分。本文介绍了一种基于STM32的智能空调设计方案,可以自动地根据环境温度进行温度调节。 二、…

单价20块蓝牙耳机卖爆越南市场,现象级爆款出现?

以儒道为文化底蕴的越南,是与中国最为相近的东南亚国家,"快速增长的劳动人口相对年轻的社会群体"是很多人对越南这个国家的基本认知。背靠庞大的Z世代用户群体,越南社会年轻化消费需求暴涨,手机与数码品类商品作为“年轻…

OpenCL编程指南-9.1命令、队列、事件

概述 命令队列是OpenCL的核心。平台定义了一个上下文,其中包含一个或多个计算设备。每个计算设备可以有一个或多个命令队列。提交到这些队列的命令将完成OpenCL程序的具体工作。 在一个简单的OpenCL程序中,提交到一个命令队列的命令会按顺序执行。一个…

ThinkPHP5使用phpqrcode生成二维码

生成指定跳转地址二维码图片: 首先将下载好的phpqrcode.php文件放到指定目录内(我这里用的放在public/phpqrcode目录下),准备调用 之后控制器中调用 public function qrcode(){require_once "./phpqrcode/phpqrcode.php&quo…

浅谈能源管理系统在电子厂房中的应用

贾丽丽 安科瑞电气股份有限公司上海嘉定201801 摘要:以能耗管理系统在工业厂房的应用为例,介绍了系统架构及功能。重点分析能耗管理系统在工业厂房实施过程中遇到的难点,并对系统采集的数据进行分析,提出了相应的节能措施&#…

【百问百答】可靠性基础知识第七期

1.什么是振动频率范围? 振动频率范围表示振动试验由某个频率点到另一个频率点进行往复扫频。 例如:试验频率范围5~500Hz,表示5Hz到500Hz进行往复扫频 2.什么是振动量? 振动量:通常用加速度和位移来表示; 加速度:表…