二十三种设计模式
2 工厂方法模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
《设计模式》一书中,工厂模式被分为了三种:简单工厂、工厂方法和抽象工厂。(不过,在书中作者将简单工厂模式看作是工厂方法模式的一种特例。)
接下来我会介绍三种工厂模式的原理及使用
- 简单工厂模式(不属于GOF的23种经典设计模式)
- 工厂方法模式
- 抽象工厂模式
2.1 需求: 模拟发放奖品业务
需求: 为了让我们的案例更加贴近实际开发, 这里我们来模拟一下互联网电商中促销拉新下的业务场景, 新用户注册立即参与抽奖活动 ,奖品的种类有: 打折券, 免费优酷会员,小礼品.

2.2 原始开发方式
不考虑设计原则,不使用设计模式的方式进行开发
在不考虑任何代码的可扩展性的前提下,只为了尽快满足需求.我们可以这样去设计这个业务的代码结构:
1) 实体类
| 名称 | 描述 |
|---|---|
| AwardInfo | 获奖信息对应实体类 |
| DiscountInfo | 打折券信息对应实体类 |
| YouKuMember | 优酷会员对应实体类 |
| SmallGiftInfo | 小礼品信息对应实体类 |
| DiscountResult | 打折券操作响应结果封装类 |
public class AwardInfo {private String uid; //用户唯一IDprivate Integer awardType; //奖品类型: 1 打折券 ,2 优酷会员,3 小礼品private String awardNumber; //奖品编号Map<String, String> extMap; //额外信息}public class DiscountInfo {//属性信息省略......
}public class YouKuMember {//属性信息省略......
}public class SmallGiftInfo {private String userName; // 用户姓名private String userPhone; // 用户手机private String orderId; // 订单IDprivate String relAddress; // 收货地址}public class DiscountResult {private String status; // 状态码private String message; // 信息
}
2) 服务层
| 名称 | 功能 | 描述 |
|---|---|---|
| DiscountService | DiscountResult sendDiscount(String uid,String number) | 模拟打折券服务 |
| YouKuMemberService | void openMember(String bindMobile , String number) | 模拟赠送优酷会员服务 |
| SmallGiftService | Boolean giveSmallGift(SmallGiftInfo smallGiftInfo) | 模拟礼品服务 |
public class DiscountService {public DiscountResult sendDiscount(String uid, String number){System.out.println("向用户发放打折券一张: " + uid + " , " + number);return new DiscountResult("200","发放打折券成功");}
}public class YouKuMemberService {public void openMember(String bindMobile , String number){System.out.println("发放优酷会员: " + bindMobile + " , " + number);}
}public class SmallGiftService {public Boolean giveSmallGift(SmallGiftInfo smallGiftInfo){System.out.println("小礼品已发货,获奖用户注意查收! " + JSON.toJSON(smallGiftInfo));return true;}
}
3) 控制层
| 名称 | 功能 | 描述 |
|---|---|---|
| DeliverController | ResponseResult awardToUser(AwardInfo awardInfo) | 按照类型的不同发放商品 奖品类型: 1 打折券 ,2 优酷会员,3 小礼品 |
public class DeliverController {/*** 按照类型的不同发放商品* 奖品类型: 1 打折券 ,2 优酷会员,3 小礼品*/public void awardToUser(AwardInfo awardInfo){if(awardInfo.getAwardType() == 1){ //打折券DiscountService discountService = new DiscountService();DiscountResult result = discountService.sendDiscount(awardInfo.getUid(), awardInfo.getAwardNumber());System.out.println("打折券发放成功!"+ JSON.toJSON(result));}else if(awardInfo.getAwardType() == 2){ //优酷会员//获取用户手机号String bindMobile = awardInfo.getExtMap().get("phone");//调用serviceYouKuMemberService youKuMemberService = new YouKuMemberService();youKuMemberService.openMember(bindMobile,awardInfo.getAwardNumber());System.out.println("优酷会员发放成功!");}else if(awardInfo.getAwardType() == 3){ /*小礼品封装收货用户信息*/SmallGiftInfo smallGiftInfo = new SmallGiftInfo();smallGiftInfo.setUserName(awardInfo.getExtMap().get("username"));smallGiftInfo.setOrderId(UUID.randomUUID().toString());smallGiftInfo.setRelAddress(awardInfo.getExtMap().get("adderss"));SmallGiftService smallGiftService = new SmallGiftService();Boolean isSuccess = smallGiftService.giveSmallGift(smallGiftInfo);System.out.println("小礼品发放成功!" + isSuccess);}}}
4) 测试
通过单元测试,来对上面的接口进行测试,验证代码质量.
public class TestApi01 {//测试发放奖品接口@Testpublic void test01(){DeliverController deliverController = new DeliverController();//1. 发放打折券优惠AwardInfo info1 = new AwardInfo();info1.setUid("1001");info1.setAwardType(1);info1.setAwardNumber("DEL12345");deliverController.awardToUser(info1);//2. 发放优酷会员AwardInfo info2 = new AwardInfo();info2.setUid("1002");info2.setAwardType(2);info2.setAwardNumber("DW12345");Map<String,String> map = new HashMap<>();map.put("phone","13512341234");info2.setExtMap(map);deliverController.awardToUser(info2);//2. 发放小礼品AwardInfo info3 = new AwardInfo();info3.setUid("1003");info3.setAwardType(3);info3.setAwardNumber("SM12345");Map<String,String> map2 = new HashMap<>();map2.put("username","大远");map2.put("phone","13512341234");map2.put("address","北京天安门");info3.setExtMap(map2);deliverController.awardToUser(info3);}
}
对于上面的实现方式,如果我们有想要添加的新的奖品时,势必要改动DeliverController的代码,违反开闭原则.而且如果有的抽奖接口出现问题,那么对其进行重构的成本会非常高.
除此之外代码中有一组if分支判断逻辑,现在看起来还可以,但是如果经历几次迭代和拓展,后续ifelse肯定还会增加.到时候接手这段代码的研发将会十分痛苦.
2.3 简单工厂模式
2.3.1 简单工厂模式介绍
简单工厂不是一种设计模式,反而比较像是一种编程习惯。简单工厂模式又叫做静态工厂方法模式(static Factory Method pattern),它是通过使用静态方法接收不同的参数来返回不同的实例对象.
实现方式:
定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。
适用场景:
(1)需要创建的对象较少。
(2)客户端不关心对象的创建过程。
2.3.2 简单工厂原理
简单工厂包含如下角色:
- 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品 :实现或者继承抽象产品的子类
- 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

2.3.3 简单工厂模式重构代码
1) service
/*** 免费商品发放接口* @author spikeCong* @date 2022/9/8**/
public interface IFreeGoods {ResponseResult sendFreeGoods(AwardInfo awardInfo);}
/*** 模拟打折券服务* @author spikeCong* @date 2022/9/8**/
public class DiscountFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {System.out.println("向用户发放一张打折券: " + awardInfo.getUid() + " , " + awardInfo.getAwardNumber());return new ResponseResult("200","打折券发放成功!");}
}/*** 小礼品发放服务* @author spikeCong* @date 2022/9/8**/
public class SmallGiftFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {SmallGiftInfo smallGiftInfo = new SmallGiftInfo();smallGiftInfo.setUserPhone(awardInfo.getExtMap().get("phone"));smallGiftInfo.setUserName(awardInfo.getExtMap().get("username"));smallGiftInfo.setAddress(awardInfo.getExtMap().get("address"));smallGiftInfo.setOrderId(UUID.randomUUID().toString());System.out.println("小礼品发放成,请注意查收: " + JSON.toJSON(smallGiftInfo));return new ResponseResult("200","小礼品发送成功",smallGiftInfo);}
}/*** 优酷 会员服务* @author spikeCong* @date 2022/9/8**/
public class YouKuMemberFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {String phone = awardInfo.getExtMap().get("phone");System.out.println("发放优酷会员成功,绑定手机号: " + phone);return new ResponseResult("200","优酷会员发放成功!");}
}
2) factory
/*** 具体工厂: 生成免费商品* @author spikeCong* @date 2022/9/9**/
public class FreeGoodsFactory {public static IFreeGoods getInstance(Integer awardType){IFreeGoods iFreeGoods = null;if(awardType == 1){ //打折券iFreeGoods = new DiscountFreeGoods();}else if(awardType == 2){ //优酷会员iFreeGoods = new YouKuMemberFreeGoods();}else if(awardType == 3){ //小礼品iFreeGoods = new SmallGiftFreeGoods();}return iFreeGoods;}
}
3)controller
public class DeliverController {//发放奖品public ResponseResult awardToUser(AwardInfo awardInfo){try {IFreeGoods freeGoods = FreeGoodsFactory.getInstance(awardInfo.getAwardTypes());ResponseResult responseResult = freeGoods.sendFreeGoods(awardInfo);return responseResult;} catch (Exception e) {e.printStackTrace();return new ResponseResult("201","奖品发放失败!");}}
}
4) 测试
通过单元测试,来对上面的接口进行测试,验证代码质量.
public class TestApi02 {DeliverController deliverController = new DeliverController();@Testpublic void test01(){//1. 发放打折券优惠AwardInfo info1 = new AwardInfo();info1.setUid("1001");info1.setAwardTypes(1);info1.setAwardNumber("DEL12345");ResponseResult result = deliverController.awardToUser(info1);System.out.println(result);}@Testpublic void test02(){//2. 发放优酷会员AwardInfo info2 = new AwardInfo();info2.setUid("1002");info2.setAwardTypes(2);info2.setAwardNumber("DW12345");Map<String,String> map = new HashMap<>();map.put("phone","13512341234");info2.setExtMap(map);ResponseResult result1 = deliverController.awardToUser(info2);System.out.println(result1);}@Testpublic void test03(){//3. 发放小礼品AwardInfo info3 = new AwardInfo();info3.setUid("1003");info3.setAwardTypes(3);info3.setAwardNumber("SM12345");Map<String,String> map2 = new HashMap<>();map2.put("username","大远");map2.put("phone","13512341234");map2.put("address","北京天安门");info3.setExtMap(map2);ResponseResult result2 = deliverController.awardToUser(info3);System.out.println(result2);}
}
2.3.4 简单工厂模式总结
优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。
2.4 工厂方法模式
2.4.1 工厂方法模式介绍
工厂方法模式 Factory Method pattern,属于创建型模式.
概念: 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
2.4.2 工厂方法模式原理
工厂方法模式的目的很简单,就是封装对象创建的过程,提升创建对象方法的可复用性。
工厂方法模式的主要角色:
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
- 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
我们直接来看看工厂方法模式的 UML 图:

2.4.3 工厂方法模式重构代码
为了提高代码扩展性,我们需要将简单工厂中的if分支逻辑去掉,通过增加抽象工厂(生产工厂的工厂)的方式,让具体工厂去进行实现,由具体工厂来决定实例化哪一个具体的产品对象.
抽象工厂
public interface FreeGoodsFactory {IFreeGoods getInstance();
}
具体工厂
public class DiscountFreeGoodsFactory implements FreeGoodsFactory {@Overridepublic IFreeGoods getInstance() {return new DiscountFreeGoods();}
}public class SmallGiftFreeGoodsFactory implements FreeGoodsFactory {@Overridepublic IFreeGoods getInstance() {return new SmallGiftFreeGoods();}
}
Controller
public class DeliverController {/*** 按照类型的不同发放商品*/public ResponseResult awardToUser(AwardInfo awardInfo){FreeGoodsFactory freeGoodsFactory = null;if(awardInfo.getAwardType() == 1){freeGoodsFactory = new DiscountFreeGoodsFactory();}else if(awardInfo.getAwardType() == 2){freeGoodsFactory = new SmallGiftFreeGoodsFactory();}IFreeGoods freeGoods = freeGoodsFactory.getInstance();System.out.println("=====工厂方法模式========");ResponseResult result = freeGoods.sendFreeGoods(awardInfo);return result;}}
从上面的代码实现来看,工厂类对象的创建逻辑又耦合进了 awardToUser() 方法中,跟我们最初的代码版本非常相似,引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了。
那怎么 来解决这个问题呢?
我们可以为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。
/*** 用简单方法模式实现: 工厂的工厂,作用是不需要每次创建新的工厂对象* @author spikeCong* @date 2022/9/9**/
public class FreeGoodsFactoryMap {private static final Map<Integer,FreeGoodsFactory> cachedFactories = new HashMap<>();static{cachedFactories.put(1, new DiscountFreeGoodsFactory());cachedFactories.put(2, new SmallGiftFreeGoodsFactory());}public static FreeGoodsFactory getParserFactory(Integer type){if(type == 1){FreeGoodsFactory freeGoodsFactory = cachedFactories.get(1);return freeGoodsFactory;}else if(type ==2){FreeGoodsFactory freeGoodsFactory = cachedFactories.get(2);return freeGoodsFactory;}return null;}
}
Controller
/*** 发放奖品接口* @author spikeCong* @date 2022/9/7**/
public class DeliverController {/*** 按照类型的不同发放商品*/public ResponseResult awardToUser(AwardInfo awardInfo){//根据类型获取工厂FreeGoodsFactory goodsFactory = FreeGoodsFactoryMap.getParserFactory(awardInfo.getAwardType());//从工厂中获取对应实例IFreeGoods freeGoods = goodsFactory.getInstance();System.out.println("=====工厂方法模式========");ResponseResult result = freeGoods.sendFreeGoods(awardInfo);return result;}
}
现在我们的代码已经基本上符合了开闭原则,当有新增的产品时,我们需要做的事情包括:
- 创建新的产品类,并且让该产品实现抽象产品接口
- 创建产品类对应的具体工厂,并让具体工厂实现抽象工厂
- 将新的具体工厂对象,添加到FreeGoodsFactoryMap的cachedFactories中即可,需要改动的代码改动的非常少.
2.4.4 工厂方法模式总结
工厂方法模优缺点
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
什么时候使用工厂方法模式
- 需要使用很多重复代码创建对象时,比如,DAO 层的数据对象、API 层的 VO 对象等。
- 创建对象要访问外部信息或资源时,比如,读取数据库字段,获取访问授权 token 信息,配置文件等。
- 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
- 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。这些对象的特性是:有限、可重用,使用工厂方法模式可以有效节约资源。
- 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等。
相关文章:
二十三种设计模式
2 工厂方法模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通…...
Spring Boot 异步编程深入剖析
Spring Boot 异步编程深入剖析 1. 异步方法的使用 原理深度解析 Spring Boot 的异步方法基于 Spring 的 AOP(面向切面编程)实现。当在方法上添加 Async 注解时,Spring 会为该方法所在的类创建一个代理对象。当调用该异步方法时,…...
SqlSugar 语法糖推荐方式
//方式1:var dd _repository._Db.Queryable<ConfigAggregateRoot, UserRoleEntity>((o, p) > o.Id p.Id).Select((o, p) > new{o.Id,o.Remark,p.RoleId,});//方式2:不推荐使用,建议优先使用 Lambda 表达式,因为它更…...
SQL 全面指南:从基础语法到高级查询与权限控制
SQL:全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准 。 一、SQL通用语法 在学习具体的SQL语句之前,先来了解一下SQL语言的同于语法。 1). SQL语句可以单行或多…...
Spring Cloud Gateway 网关的使用
在之前的学习中,所有的微服务接口都是对外开放的,这就意味着用户可以直接访问,为了保证对外服务的安全性,服务端实现的微服务接口都带有一定的权限校验机制,但是由于使用了微服务,就需要每一个服务都进行一…...
【Spring Cloud Alibaba】基于Spring Boot 3.x 搭建教程
目录 前言一、开发环境二、简介 1.主要功能2.组件 三、搭建过程 1 - 主体工程搭建2 - 服务注册与发现组件 —— Nacos的安装3 - 服务注册与发现 —— 服务提供者4 - 服务注册与发现 —— 服务消费者5 - 服务配置中心6 - OpenFeign服务接口调用7 - OpenFeign高级特性8 - Spring…...
JavaWeb-jdk17安装
下载jdk17 地址:https://www.oracle.com/java/technologies/downloads/#jdk17-windows 安装jdk 配置环境变量 右键点击我的电脑>属性>高级系统设置>环境变量 在系统变量Path变量中添加 测试 java -version javac -version...
docker关闭mysql端口映射的使用
需求 项目中的数据库为mysql,如果将端口映射到宿主机上,容易被工具扫描出,且随着国产化的进程推进,mysql将不被允许。为了提高安全性与满足项目需求,这里采用隐藏mysql端口方式,不映射宿主机端口ÿ…...
【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享
更多银河麒麟操作系统产品及技术讨论,欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer…...
算法1-4 蜜蜂路线
题目描述 一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房 m 开始爬到蜂房 n,m<n,有多少种爬行路线?(备注:题面有误,右上角应为 n−…...
Android 常见View的防抖
在开发Android应用时,我们经常会遇到用户快速点击按钮或者频繁触发某个事件的情况。这种行为可能会导致不必要的重复操作,例如多次提交表单、重复加载数据等。为了避免这些问题,我们需要对这些事件进行防抖处理。本文将详细介绍如何在Kotlin中…...
数据库原理SQL查询(习题+知识点)
一、查询学生表所有学生记录 1.题目内容代码编写 select * from stu; 2.知识点提醒 1)选择表中的所有属性列有两种方法 在select关键字后列出所有列名若列的显示顺序与其在表中的顺序相同,则也可用 * 表示所有列 二、查询学生表中部分信息 1.题目内…...
安路FPGA开发入门:软件安装与点灯与仿真(TangDynasty ModelSim)
文章目录 前言软件安装开发软件仿真软件 点灯测试代码编写与编译引脚分配固件下载 仿真测试ModelSim添加仿真库TangDynasty仿真设置进行仿真 后记 前言 最近因为工作需要用安路的FPGA,这里对安路FPGA开发相关流程做个记录。作为测试只需要一个核心板(我这…...
Java 导出大数据到 Excel 表格
背景 之前的项目一直是用XSSFWorkbook来做 Excel 导出,在遇到大数据导出时,经常会遇到 OOM。在 Apache Poi 3.8 之后的版本提供的 SXSSFWorkbook 可以优雅的解决这个问题。 原理 SXSSFWorkbook 被称为流式 API,主要是因为它采用了流式写入…...
浅克隆与深克隆区别
package d12_api_object;public class Test2 {public static void main(String[] args) throws CloneNotSupportedException {//目标:掌握Object类提供的对象克隆方法//1、protected Object clone():对象克隆User u1 new User(1,"min","1120",…...
关于服务器cpu过高的问题排查
1.定位是哪个程序造成的cpu过高 如果有云服务器,就用云服务器自带的监控功能,查时间段 如果没有,则使用: ps -eo pid,comm,pcpu,pmem,cputime --sort-cputime | head -n 100 2.定位到问题 发现是uwsgi的cpu消耗过高࿰…...
【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二)
【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二 完结) 缓冲区既属于操作系统,也属于 JVM,具体取决于你讨论的是哪个层面的缓冲区。下面我会详细解释这两者的区别和联系。 1. …...
RPA 职业前景:个人职场发展的 “新机遇”
1. RPA职业定义与范畴 1.1 RPA核心概念 机器人流程自动化(RPA)是一种通过软件机器人模拟人类操作,自动执行重复性、规则性任务的技术。RPA的核心在于其能够高效、准确地处理大量数据和流程,减少人工干预,从而提高工作…...
如何实现小数据的大智能?
大数据可以通过从态到势、从感到知的态势感知过程计算出可能性,如各种大模型,而要通过小数据、小样本获得好的预测结果,可以通过从势到态、从知到感的势态知感过程算计出可能性。 一般情况下,大家常常会提到了大数据和小数据在态势…...
打开 Windows Docker Desktop 出现 Docker Engine Stopped 问题
一、关联文章: 1、Docker Desktop 安装使用教程 2、家庭版 Windows 安装 Docker 没有 Hyper-V 问题 3、安装 Windows Docker Desktop - WSL问题 二、问题解析 打开 Docker Desktop 出现问题,如下: Docker Engine Stopped : Docker引擎停止三、解决方法 1、检查服务是否…...
基于单片机和蓝牙通讯的简易钢琴控制装置设计
摘要:本文设计了一个基于单片机和蓝牙通讯的简易钢琴演奏控制装置,在 Proteus 中设计绘制了系统电路原理图,在 Keil 中编写了单片机控制程序并导入 Proteus电路原理图中进行了软、硬件交互仿真,设置了手机蓝牙串口调试的键盘设置及…...
Linux常见操作命令以及编辑器VI命令
一.复制(cp)和移动(mv) 1.复制文件 格式:cp 源文件 目标文件 2.复制目录 格式:cp -r 源文件夹 目标文件夹 3.重命名和移动 重命名格式:mv 源文件 目标文件 移动格式:mv 源文件 目录/源文件 二.查看文件内容 1.cat命令 格式&#x…...
React Native从入门到进阶详解
React Native知识框架从入门到进阶的问题。首先需要结合我搜索到的资料来整理出结构化的内容。证据中有多本书籍和文章,可能会涉及不同的章节和重点,需要仔细梳理。 首先,根据邱鹏源的《React Native精解与实战》将知识分为入门和进阶两大部分…...
STL——list的介绍和模拟实现
前言 本篇博客我们将要开始介绍list这个容器,list是带头双向循环链表,STL标准模板库中实现了list这样方便我们去使用,那么本篇博客我们将脱下list的神秘外衣,介绍它的使用以及模拟实现。 list的介绍 list的底层是带头双向循环链…...
go前后端开源项目go-admin,本地启动
https://github.com/go-admin-team/go-admin 教程 1.拉取项目 git clone https://github.com/go-admin-team/go-admin.git 2.更新整理依赖 go mod tidy会整理依赖,下载缺少的包,移除不用的,并更新go.sum。 # 更新整理依赖 go mod tidy 3.编…...
go 分布式redis锁的实现方式
go 语言以高并发著称。那么在实际的项目中 经常会用到锁的情况。比如说秒杀抢购等等场景。下面主要介绍 redis 布式锁实现的两种高并发抢购场景。其实 高并发 和 分布式锁 是一个互斥的两个状态: 方式一 setNX: 使用 redis自带的API setNX 来实现。能解决…...
深入理解递归:从原理到C++实践
什么是递归? 递归(Recursion)是编程中一种强大的技术,其核心思想是:函数直接或间接地调用自身。如同俄罗斯套娃一般,每个函数调用都会解开问题的一个层级,直到达到基础条件。 递归三要素&…...
【2025年15期免费获取股票数据API接口】实例演示五种主流语言获取股票行情api接口之沪深A股解禁限售数据获取实例演示及接口API说明文档
在近一至两年期间,股票量化分析逐步成为备受关注的热门议题。对于投身于该领域工作而言,首要步骤便是获取全面且精准的股票数据。无论是实时交易数据、历史交易记录、财务数据,亦或是基本面信息,这些数据均是开展量化分析过程中不…...
MyBatis-Plus 入门详解:从零搭建高效持久层
一、MyBatis-Plus 简介 MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在保留 MyBatis 原生功能的基础上,提供了全自动化的 CRUD 操作、强大的分页插件、代码生成器等功能,显著减少开发工作量。与原生 MyBatis 相比&…...
阿里云物联网获取设备属性api接口:QueryDevicePropertyData
阿里云物联网接口:QueryDevicePropertyData 说明:调用该接口查询指定设备或数字孪生节点,在指定时间段内,单个属性的数据 比如提取上传到物联网的温度数据 api文档:QueryDevicePropertyData_物联网平台_API文档-阿里…...
