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

C# 创建型设计模式----工厂模式

1 、什么是工厂模式

简单来说就是由一个对象去生成不同的对象,工厂模式是用工厂方法代替new操作的一种模式。工厂方法封装了多个相关联类的new方法,每次实例化这些类的时候不需要new多次,只需要调用工厂类的对应方法即可实例化这些类,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式主要有三种类型:简单工厂(不介绍)工厂方法抽象工厂

2、工厂模式的作用

在创建对象时必然需要new该对象,当需要更改对象时,需要把项目中所有地方都修改一遍,这显然违背了软件设计的开闭原则。如果使用工厂来生成对象,那么我们只需要跟工厂打交道就可以了。如果要更新对象时,直接在工厂里更换即可。这就实现了对象解耦。

所以工厂模式主要用来解耦代码,将对象的创建和使用分离,使得代码更加灵活和可维护。

3、工厂方法

3.1、工厂方法模式的主要角色:

抽象工厂:在抽象工厂类中声明了工厂方法,用于返回一个产品。提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。

具体工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的工厂方法,完成具体产品的创建。并可由客户端调用,返回一个具体产品类的实例。

抽象产品:它是定义产品的接口,定义了产品的规范,描述了产品的主要特性和功能,是工厂方法模式所创建对象的公共父类

具体产品:它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间相互对应。

3.2、创建工厂方法

 抽象工厂:提供基类,通俗理解就是。有这么一个专门生产电蒸锅的集团架构(别问为什么是电蒸锅,因为我现在想买)。集团不提供锅,只提供流水线的基建,和产品的基本概念。

 /// <summary>///抽象工厂--电蒸锅集团,专门生产各种电蒸锅/// </summary>public abstract class ElectricFactory{/// <summary>/// 声明获取抽象产品类方法(具体实现在其子类)--提供生产电蒸锅的流水线,流水线具体怎么生产,生产哪种集团不管/// </summary>/// <returns></returns>public abstract Electric GetElectric();}

具体工厂:继承抽象工厂--也就是具体的生产厂家,都是继承集团的流水线并定义里面具体的生产方式

/// <summary>
/// 具体工厂-美的流水线
/// </summary>
public class MDElectricFactory : ElectricFactory//美的属于该集团下的工厂
{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//美的使用集团提供的流水线,集团提供什么,美的就能使用什么{Console.WriteLine("美的生产了一个锅");return new MDElectric();//返回具体产品-美的电蒸锅}
}
/// <summary>
/// 具体工厂-苏泊尔流水线
/// </summary>
public class SBRElectricFactory : ElectricFactory//苏泊尔属于该集团下的工厂
{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//使用集团提供的流水线{Console.WriteLine("苏泊尔生产了一个锅");return new SBRElectric();//返回具体产品-苏泊尔电蒸锅}
}

抽象产品:集团告诉你这是电蒸锅,它有什么功能,下面的工厂生产的产品得有这个功能,至于功能怎么实现的集团不管。

/// <summary>
/// 抽象产品电蒸锅---集团定义的电蒸锅整个品类
/// </summary>
public abstract class Electric
{/// <summary>/// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。/// </summary>public abstract void Fun();/// <summary>/// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。/// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),/// 例如电蒸锅的预约功能就很大众,可以有,/// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。/// </summary>public void AddFunction(string name){Console.WriteLine($"{name}加了一个预约功能");}
}

具体产品:电蒸锅的蒸东西的功能具体实现方式

  /// <summary>/// 具体产品-美的电蒸锅/// </summary>public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电蒸锅/// </summary>public class SBRElectric : Electric//这是苏泊尔电蒸锅{public override void Fun(){Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");}}

使用:

private void WTBtn_Click(object sender, EventArgs e)
{ElectricFactory electric;//创建了一个电蒸锅集团。electric = new MDElectricFactory();//美的接入集团var DZG = electric.GetElectric();//美的使用集团生产线,定义生产线的具体流程并生产一个锅DZG.Fun();//这个锅实现具体的功能electric = new SBRElectricFactory();//苏泊尔接入集团var DZG1 = electric.GetElectric();//苏泊尔使用集团生产线,定义生产线的具体流程并生产一个锅DZG1.Fun();//这个锅实现具体的功能DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。
}

运行结果:

通过调用方式可以看出,不同产品的生产由原来的总工厂变为了各个分工厂去负责。

用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。

这就是一整个工厂方法。当然这样看下来估计也是懵懂的不知道它有什么作用。

我再用文字尝试说明一下:

来设想你现在需要开发一个电商平台的订单模块,其中需要生成不同类型的订单,比如普通订单、促销订单、团购订单等。每个订单里面有很多的参数。

按照常规的方式,我们直接创建每个订单类,然后全部new出来即可, 这样就没必要创建什么工厂类了对吧?

假设订单类名是OrderA、OrderB、OrderC。有很多参数的情况下New就得

OrderA A=new OrderA(参数1,参数2,.....);

要使用里面具体方法还得

A.方法1();A.方法2();........

但是现在你有各种各样的订单,这些订单是你不同的同事去开发的。如果按你上面的做法,首先你需要知道每一个订单类的情况,你需要知道要成功new出一个具体的订单类需要哪些参数、需要执行哪些方法。但是这明显是不现实的,你没有时间去看源码,甚至看不到源码。

因为你的工作只是new出订单类并调用里面的方法罢了,而每个订单类具体怎么写,其实你不需要知道,这个时候每个订单类对应一个具体的工厂类,你只需要调用工厂里的创建产品方法就行了。

再者从单依职责原则,解耦合来考虑。如果按常规new OrderA的写法,你的同事某个订单类修改了,势必会导致你写的程序会直接创建报错,你就得跟着修改。但是使用了工厂方法,根本不会影响你,因为你不参与创建实例,你的程序也不需要任何的改动。你的同事如何修改订单类跟你也没关系。

嗯.....这样说不知道有没有说明白它的作用。。。

4、抽象工厂

上面工厂模式不管工厂怎么拆分抽象,都只是针对一类产品,直接生成实例,这些工厂只生产同种类产品。

但是抽象工厂模式不同,抽象工厂模式并不直接生成实例, 而是用于对产品类簇的创建。

通俗点来讲就是:简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的。

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

抽象工厂的最大好处在于交换产品系列非常方便,只需要改变具体工厂即可使用不同的产品配置。

总的来说工厂方法模式一个工厂只生产一个产品,抽象工厂模式一个工厂生产多个产品,形成一个产品套餐,而多个工厂组成套餐系列。

4.1、抽象工厂模式的主要角色:

        抽象工厂:在抽象工厂类中声明了多个工厂方法,用于返回多个产品。提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。

  具体产品工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的多个工厂方法,完成多个具体产品的创建。

  抽象产品:它是定义一个产品的接口,定义了一个产品的规范,描述了一个产品的主要特性和功能。抽象工厂模式有多个抽象产品。

  具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

 4.2 创建方式

抽象工厂:有多少个系列就可以创建多少个抽象工厂类。本实例只创建了一个电器系列的工厂。里面可以有许多同系列的电器产品。

/// <summary>
///抽象工厂--电器集团,专门生产各种电器
/// </summary>
public abstract class ElectricFactory
{/// <summary>/// 生产电蒸锅/// </summary>/// <returns></returns>public abstract Electric GetElectric();/// <summary>/// 生产电饭煲/// </summary>/// <returns></returns>public abstract Rice GetRice();
}

具体工厂:同一系列可以创建多个具体的工厂,负责同一系列下的不同产品出的创建。本示例是电器下的电蒸锅和电饭煲,当然还可以电视机,烧水壶啥的。

 /// <summary>/// 具体工厂-美的工厂/// </summary>public class MDFactory : ElectricFactory//美的属于该集团下的工厂{public override Electric GetElectric(){Console.WriteLine("美的生产了一个电蒸锅");return new MDElectric();//返回具体产品-美的电蒸锅}public override Rice GetRice(){Console.WriteLine("美的生产了一个电饭煲");return new MDRice();}}/// <summary>/// 具体工厂-苏泊尔工厂/// </summary>public class SBRFactory : ElectricFactory//苏泊尔属于该集团下的工厂{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//使用集团提供的流水线{Console.WriteLine("苏泊尔生产了一个电蒸锅");return new SBRElectric();//返回具体产品-苏泊尔电蒸锅}public override Rice GetRice(){Console.WriteLine("苏泊尔生产了一个电饭煲");return new SBRRice();}}

抽象产品:有多少个不同产品就创建多少个抽象产品类。

 /// <summary>/// 抽象产品电蒸锅---集团定义的电蒸锅整个品类/// </summary>public abstract class Electric{/// <summary>/// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。/// </summary>public abstract void Fun();/// <summary>/// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。/// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),/// 例如电蒸锅的预约功能就很大众,可以有,/// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。/// </summary>public void AddFunction(string name){Console.WriteLine($"{name}加了一个预约功能");}}/// <summary>/// 抽象产品-电饭煲/// </summary>public abstract class Rice{public abstract void Fun();}

具体产品:不同产品继承不同抽象类。

 /// <summary>/// 具体产品-美的电蒸锅/// </summary>public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电蒸锅/// </summary>public class SBRElectric : Electric//这是苏泊尔电蒸锅{public override void Fun(){Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");}}/// <summary>/// 具体产品-美的电饭煲/// </summary>public class MDRice : Rice//这是美的电饭煲{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电饭煲蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电饭煲/// </summary>public class SBRRice : Rice//这是苏泊尔电饭煲{public override void Fun(){Console.WriteLine("苏泊尔电饭煲蒸东西的功能是用中火蒸东西");}}

调用:

  private void WTBtn_Click(object sender, EventArgs e){ElectricFactory electric;//创建了一个电器集团。electric = new MDFactory();//美的工厂var DZG = electric.GetElectric();//生产一个电蒸锅锅DZG.Fun();//这个锅实现具体的功能var DFB = electric.GetRice();//生产一个电饭煲DFB.Fun();//换个工厂electric = new SBRFactory();//苏泊尔工厂var DZG1 = electric.GetElectric();//生产一个电蒸锅锅DZG1.Fun();//这个锅实现具体的功能DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。var DFB1 = electric.GetRice();//生产一个电饭煲DFB1.Fun();}

上面实例可以看出创建一个工厂可以产出不同的产品。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

 END........................................................................

相关文章:

C# 创建型设计模式----工厂模式

1 、什么是工厂模式 简单来说就是由一个对象去生成不同的对象&#xff0c;工厂模式是用工厂方法代替new操作的一种模式。工厂方法封装了多个相关联类的new方法&#xff0c;每次实例化这些类的时候不需要new多次&#xff0c;只需要调用工厂类的对应方法即可实例化这些类&#x…...

java中Scanner的nextLine和next方法

思考&#xff0c;输入1 2 3 4 5加上enter&#xff0c;输出什么 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int[][] m new int[2][2];for (int i 0; i < 2; i) {for (int j 0; j < 2;…...

2024年全国山洪径流模拟与洪水危险性评价技术及典型地区洪水淹没及损失分析

洪水淹没危险性&#xff08;各种年遇型洪水淹没&#xff09;是洪水损失评估、风险评估及洪水应急和管理规划等工作的重要基础。当前开展洪水危险性研究工作中的主要困难之一是水文资料稀缺&#xff0c;尤其是径流资料稀缺&#xff0c;既包括径流观测资料在时间上的短缺&#xf…...

CDC 同步数据需要的MySQL数据权限

授权命令如下: grant Replication client on *.* to username%; grant Replication slave on *.* to username%; flush privileges;...

Ubuntu20.04 更新Nvidia驱动 + 安装CUDA12.1 + cudnn8.9.7

一、概述 最近客户给了几台GPU服务器,长期放置落灰那种,然后想利用起来,所以上去看看了配置,系统是Ubuntu20.04,相关的驱动版本稍嫌老一些,所以需要更新Nvidia驱动,同时在安装CUDA和CUDNN,查看了显卡型号之后,打算使用onnxruntime进行推理,对比了版本,最后选择了CUD…...

算法自学 Lesson3 - 逻辑回归(LR)

目录 背景 一、适用数据集 1. 数据集选择 1.1 领域 1.2 数据集维度 1.3 记录行&#xff08;样本数量&#xff09; 2. 本文数据集介绍 3. 数据集下载 注意 二、逻辑回归的基本原理 1. 目的 2. Sigmoid 函数 3. 类别划分 4. 召回率 三、代码 1. 导入所需包&数…...

文件IO流

1.文件流概念 2.文件创建方式 3.常用方法 4.IO流原理 &#xff08;1&#xff09;InputStream&#xff0c;OutputStream, Reader, Writer四个都是抽象类&#xff0c;无法直接new, 需要由子类继承&#xff0c;然后new子类&#xff1b; &#xff08;2&#xff09;Reader和Writer…...

拥塞控制与TCP子问题(粘包问题,异常情况等)

​拥塞控制 除了拥塞控制 以上的策越都是为了解决tcp 客户端和服务端提高效率&#xff0c;解决丢包的策略 但是拥塞控制是了为解决网络拥堵 出现了大面积丢包&#xff0c;我们发送方会判定是网络出现了问题&#xff1f; 丢包好解决&#xff0c;我们直接采用超时重传&#…...

stm32入门教程--DMA 超详细!!!

目录 简介 工作模式 1、数据转运DMA 2、ADC扫描模式DMA 简介 工作模式 1、数据转运DMA 这个例子的任务是将SRAM的数组DataA&#xff0c;转运到另一个数组DataB中&#xff0c;这个基本结构里的各个参数应该如何配置呢&#xff1f; 首先是外设站点和存储器站点的起始地址、…...

【使用Flask构建RESTful API】从零开始开发简单的Web服务!

使用Flask构建RESTful API&#xff1a;从零开始开发简单的Web服务 引言 随着Web应用程序的广泛使用&#xff0c;RESTful API已成为现代Web服务的核心技术之一。通过RESTful API&#xff0c;我们可以轻松地创建、读取、更新和删除&#xff08;CRUD&#xff09;数据&#xff0c…...

用sdcc给51单片机编译C程序

学习单片机大部分人用的是Keil uVision&#xff0c;虽然好用&#xff0c;可大部分人用的是盗版&#xff0c;其实单片机程序小的话&#xff0c;完全可以用文本编辑器&#xff08;推荐notepad)编写&#xff0c;然后用免费的sdcc来编译&#xff0c;下面介绍一下大致的过程。 sdcc…...

Java Lock LockSupport 源码

前言 相关系列 《Java & Lock & 目录》&#xff08;持续更新&#xff09;《Java & Lock & LockSupport & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Java & Lock & LockSupport & 总结》&#xff08;学习总结/最新…...

Elasticsearch基础操作入门

阅前准备知识 学习 Elasticsearch (简称 ES) 的查询方式&#xff0c;建议从以下几个步骤入手&#xff1a; 理解 Elasticsearch 的基础概念 首先要了解 Elasticsearch 的核心概念&#xff0c;例如&#xff1a; Index&#xff08;索引&#xff09;&#xff1a;相当于数据库中…...

跨域问题解决办法

跨域问题在Web开发中是一个常见的问题&#xff0c;特别是在前后端分离的开发模式下。以下是一些解决跨域问题的办法&#xff1a; 一、后端配置CORS&#xff08;跨来源资源共享&#xff09; CORS是一种机制&#xff0c;它使用额外的HTTP头来告诉浏览器一个网页的当前来源&…...

【数据结构与算法】力扣 23. 合并 K 个升序链表

题干描述 23. 合并 K 个升序链表 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 1&#xff1a; 输入&#xff1a; lists [[1,4,5],[1,3,4],[2,6]] 输出&#xff1a; [1,1,2,3,4,4,5,6]…...

Java Lock CountDownLatch 总结

前言 相关系列 《Java & Lock & 目录》&#xff08;持续更新&#xff09;《Java & Lock & CountDownLatch & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Java & Lock & CountDownLatch & 总结》&#xff08;学习总…...

vue+spreadjs开发

创建vue3项目 pnpm create vite --registryhttp://registry.npm.taobao.org安装spreadjs包 pnpm install "grapecity-software/spread-sheets17.1.7" "grapecity-software/spread-sheets-resources-zh17.1.7" "grapecity-software/spread-sheets-vu…...

针对初学者的PyTorch项目推荐

文章目录 1. MNIST手写数字识别2. CIFAR-10图像分类3. 图像风格迁移4. 文本生成&#xff08;使用RNN&#xff09;5. 简单的问答系统6. 简单的生成对抗网络&#xff08;GAN&#xff09;7. 简单的推荐系统 对于初学者来说&#xff0c;选择一些简单且具有教育意义的项目来实践PyTo…...

Helm Chart文件介绍

介绍&#xff08;这个还没有完善 &#xff0c;目前在找工作呢&#xff09; Helm是Kubernetes的包管理器&#xff0c;类似于Ubuntu中的apt、CentOS中的yum或Python中的pip&#xff0c;可以快速查找、下载和安装软件包。Helm主要由客户端组件helm和服务端组件Tiller组成&#xf…...

1Panel 是新一代的 Linux 服务器运维管理面板

1Panel 是一款新一代的 Linux 服务器运维管理面板&#xff0c;旨在通过现代化的 Web 界面帮助用户轻松管理 Linux 服务器。它集成了主机监控、文件管理、数据库管理、容器管理等功能&#xff0c;并且支持多语言和国际化&#xff0c;包括英语、中文(繁体)和日语。以下是 1Panel …...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...