Java设计模式之创建型模式(二)原型模式

原型模式

    • 1、原型模式
      • 1-1、应用场景
      • 1-2、举个 软栗子
      • 1-3、举个 硬栗子
      • 1-3、举个实务栗子

学习原型模式的目的:原型模式的目的在于通过复制现有的实例来创建新的对象,以避免通过构造函数创建对象时可能带来的性能开销,同时可以控制对象的深度复制。

1、原型模式

定义:
在Java中,原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过使用已有对象作为原型,克隆并生成新的对象,而无需显式地使用构造函数来创建对象。原型模式的核心思想是通过克隆(Clone)现有的对象来创建新的对象,这种克隆可以是浅克隆(Shallow Clone)或深克隆(Deep Clone)。

  • 浅克隆:通过调用对象的clone()方法复制对象,得到一个新的对象实例,新对象与原对象共享部分数据。对于引用类型的成员变量,浅克隆只复制其引用而不创建新的对象。
  • 深克隆:通过自定义克隆逻辑,递归地复制对象及其引用类型的成员变量,得到一个完全独立的新对象实例。深克隆会逐层复制对象及其引用的对象,保证新对象与原对象的数据完全独立。

要实现原型模式,需要满足以下条件:

  1. 被克隆的类必须实现Cloneable接口,这个接口是一个标记接口,表明该类可以被克隆。
  2. 在被克隆的类中覆写clone()方法,实现对象的克隆操作。
  3. 在使用原型模式时,通过调用对象的clone()方法创建新的对象。

通过使用原型模式,可以避免直接使用构造函数复杂地创建对象,提高对象的创建效率和灵活性。
需要注意的是,在克隆过程中如果涉及到引用类型的成员变量,如果要实现深克隆,需要对引用类型的成员变量也进行克隆操作,确保数据的独立性和完整性。
总的来说,原型模式通过克隆现有对象来创建新的对象,实现了对象的复制和创建的分离,提高了对象创建的效率和灵活性。

1-1、应用场景

Java中的原型模式适用于以下业务应用场景:

  1. 对象的创建成本高:当需要创建一个对象的成本很高,比如需要初始化大量的数据、进行复杂的计算或者远程调用等,可以使用原型模式。通过复制已有的对象,避免重复的创建过程,提高性能和效率
  2. 对象的创建过程复杂:有些对象的创建过程比较复杂,涉及到多个步骤或者依赖其他对象。在这种情况下,可以使用原型模式将一个已经初始化好的对象作为原型,通过复制来创建新对象,避免创建过程的复杂性和依赖关系的传递
  3. 动态配置对象:当需要根据用户的不同配置动态生成对象时,可以使用原型模式。通过定义一个原型对象,根据不同的配置参数进行复制,快速生成多个符合用户需求的对象
  4. 多线程环境下的对象创建:在多线程环境下,对象的创建可能会引起线程安全的问题。使用原型模式,可以避免多个线程同时创建对象,从而保证对象的安全性和一致性。

总的来说,原型模式适用于那些创建成本高、创建过程复杂、动态配置或需要在多线程环境下创建对象的场景。通过原型模式,可以通过复制现有的对象来创建新对象,提高性能、简化对象的创建过程,并保证对象的安全性和一致性。

1-2、举个 软栗子

代码如下


写个Person实现Cloneable接口:

package com.rensun.designmode.prototype_mode.shallowcopy2;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person implements Cloneable {private int id;private String name;private Address address;@Overridepublic Person clone() throws CloneNotSupportedException {return (Person) super.clone();}
}

写个Address实现Cloneable接口:

package com.rensun.designmode.prototype_mode.shallowcopy2;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
class Address implements Cloneable {private String city;private String street;@Overridepublic Address clone() throws CloneNotSupportedException {return (Address) super.clone();}
}

写个测试方法:

package com.rensun.designmode.prototype_mode.shallowcopy2;import lombok.extern.slf4j.Slf4j;/***  使用场景:*  软拷贝适用于对象的字段较简单,不包含引用类型字段*  的情况,而且希望拷贝后的对象能够及时地反映原对象*  字段的变化。例如,当对象只包含基本数据类型的字段,*  且需要对对象进行快速的拷贝操作,可以使用软拷贝。**/
@Slf4j
public class TestShallowCopy {public static void main(String[] args) {Address address = new Address("濮阳市", "挥公大道003号");Person person = new Person(1, "岳云鹏", address);try {Person copyPerson = person.clone();log.info("person: {}", person);log.info("shallow copy person: {}", copyPerson);//拷贝后的对象重新赋值copyPerson.setId(2);copyPerson.setName("小驴程序源");copyPerson.getAddress().setCity("北京市");copyPerson.getAddress().setStreet("长安街110号");log.info("------------------拷贝后的对象重新赋值如下:--------------------");log.info("person: {}", person);log.info("shallow copy person: {}", copyPerson);} catch (CloneNotSupportedException e) {log.error("Clone not supported", e);}}
}

我们看一下console输出

已连接到地址为 ''127.0.0.1:52221',传输: '套接字'' 的目标虚拟机
17:15:14.526 [main] INFO com.rensun.designmode.prototype_mode.shallowcopy2.TestShallowCopy - person: Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
17:15:14.530 [main] INFO com.rensun.designmode.prototype_mode.shallowcopy2.TestShallowCopy - shallow copy person: Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
17:15:14.530 [main] INFO com.rensun.designmode.prototype_mode.shallowcopy2.TestShallowCopy - ------------------拷贝后的对象重新赋值如下:--------------------
17:15:14.530 [main] INFO com.rensun.designmode.prototype_mode.shallowcopy2.TestShallowCopy - person: Person(id=1, name=岳云鹏, address=Address(city=北京市, street=长安街110号))
17:15:14.530 [main] INFO com.rensun.designmode.prototype_mode.shallowcopy2.TestShallowCopy - shallow copy person: Person(id=2, name=小驴程序源, address=Address(city=北京市, street=长安街110号))
已与地址为 ''127.0.0.1:52221',传输: '套接字'' 的目标虚拟机断开连接进程已结束,退出代码为 0

根据输出结果,可以看到以下信息:

原对象person的信息为:Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
浅拷贝对象copyPerson的信息为:Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
拷贝后的对象重新赋值后,原对象person的信息为:Person(id=1, name=岳云鹏, address=Address(city=北京市, street=长安街110号))
拷贝后的对象重新赋值后,浅拷贝对象copyPerson的信息为:Person(id=2, name=小驴程序源, address=Address(city=北京市, street=长安街110号))

从输出结果来看,当对拷贝后的对象copyPerson进行了修改时,原对象person的数据并没有发生变化。这是因为浅拷贝只复制了对象的引用,并没有对引用的对象进行深拷贝。因此,当拷贝对象的引用类型成员变量进行修改时,原对象的成员变量也会相应改变


1-3、举个 硬栗子

在这里插入图片描述

首先Address还是原来的它自己,Person要改写一下clone方法

package com.rensun.designmode.prototype_mode.deepcopy2;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person implements Cloneable {private int id;private String name;private Address address;@Overridepublic Person clone() throws CloneNotSupportedException {Person cPerson = (Person) super.clone();cPerson.address = this.address.clone();return cPerson;}
}

测试类还是原来的测试类,改了个名

package com.rensun.designmode.prototype_mode.deepcopy2;import lombok.extern.slf4j.Slf4j;/***  使用场景:*  硬拷贝适用于对象的字段较复杂,包含引用类型字段的情*  况,希望拷贝后的对象能够独立地管理自己的字段,不受*  原对象影响。例如,当对象包含引用类型的字段,且需要*  对对象进行深度拷贝,确保拷贝后的对象与原对象完全独*  立,可以使用硬拷贝。**/
@Slf4j
public class TestDeepCopy {public static void main(String[] args) {Address address = new Address("濮阳市", "挥公大道003号");Person person = new Person(1, "岳云鹏", address);try {Person copyPerson = person.clone();log.info("person: {}", person);log.info("shallow copy person: {}", copyPerson);//拷贝后的对象重新赋值copyPerson.setId(2);copyPerson.setName("小驴程序源");copyPerson.getAddress().setCity("北京市");copyPerson.getAddress().setStreet("长安街110号");log.info("------------------拷贝后的对象重新赋值如下:--------------------");log.info("person: {}", person);log.info("shallow copy person: {}", copyPerson);} catch (CloneNotSupportedException e) {log.error("Clone not supported", e);}}
}

但是输出结果就有了新变化:

在clone()方法中,首先调用了父类的clone()方法创建了一个新的Person对象,并进行类型转换。接着,通过调用this.address.clone()方法对地址对象进行深拷贝,将拷贝后的地址对象赋值给新创建的Person对象的地址成员变量。这样就实现了深拷贝,拷贝后的对象和原对象拥有了各自的地址对象,互不影响。

总的来说,这段代码示例展示了如何通过在clone()方法中对引用类型成员变量进行深拷贝操作,实现了深拷贝的Person类。通过这种方式,即使修改拷贝对象的引用类型成员变量,原对象的成员变量也不会受到影响

已连接到地址为 ''127.0.0.1:53498',传输: '套接字'' 的目标虚拟机
18:04:04.663 [main] INFO com.rensun.designmode.prototype_mode.deepcopy2.TestDeepCopy - person: Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
18:04:04.669 [main] INFO com.rensun.designmode.prototype_mode.deepcopy2.TestDeepCopy - shallow copy person: Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
18:04:04.669 [main] INFO com.rensun.designmode.prototype_mode.deepcopy2.TestDeepCopy - ------------------拷贝后的对象重新赋值如下:--------------------
18:04:04.669 [main] INFO com.rensun.designmode.prototype_mode.deepcopy2.TestDeepCopy - person: Person(id=1, name=岳云鹏, address=Address(city=濮阳市, street=挥公大道003号))
18:04:04.669 [main] INFO com.rensun.designmode.prototype_mode.deepcopy2.TestDeepCopy - shallow copy person: Person(id=2, name=小驴程序源, address=Address(city=北京市, street=长安街110号))
已与地址为 ''127.0.0.1:53498',传输: '套接字'' 的目标虚拟机断开连接

1-3、举个实务栗子

package com.tansun.goods.controller;import cn.hutool.json.JSONUtil;
import com.tansun.goods.prototype_mode.AnswerQuestion;
import com.tansun.goods.prototype_mode.ChoiceQuestion;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author Administrator*/
@Slf4j
@RestController
@RequestMapping
public class TestController {public String createPaper(String candidate, String number) {//选择题List<ChoiceQuestion> choiceQuestionList = new ArrayList<ChoiceQuestion>();//问答题List<AnswerQuestion> answerQuestionList = new ArrayList<AnswerQuestion>();Map<String, String> map01 = new HashMap<String, String>();map01.put("A", "JAVA2 EE");map01.put("B", "JAVA2 Card");map01.put("C", "JAVA2 ME");map01.put("D", "JAVA2 HE");map01.put("E", "JAVA2 SE");Map<String, String> map02 = new HashMap<String, String>();map02.put("A", "JAVA程序的main⽅法必须写在类⾥⾯");map02.put("B", "JAVA程序中可以有多个main⽅法");map02.put("C", "JAVA程序中类名必须与⽂件名⼀样");map02.put("D", "JAVA程序的main⽅法中如果只有⼀条语句,可以不⽤{}(⼤括号)括起来");Map<String, String> map03 = new HashMap<String, String>();map03.put("A", "变量由字⺟、下划线、数字、$符号随意组成;");map03.put("B", "变量不能以数字作为开头;");map03.put("C", "A和a在java中是同⼀个变量;");map03.put("D", "不同类型的变量,可以起相同的名字;");Map<String, String> map04 = new HashMap<String, String>();map04.put("A", "STRING");map04.put("B", "x3x;");map04.put("C", "void");map04.put("D", "de$f");Map<String, String> map05 = new HashMap<String, String>();map05.put("A", "31");map05.put("B", "0");map05.put("C", "1");map05.put("D", "2");choiceQuestionList.add(new ChoiceQuestion("JAVA所定义的版本中不包括", map01, "D"));choiceQuestionList.add(new ChoiceQuestion("下列说法正确的是", map02, "A"));choiceQuestionList.add(new ChoiceQuestion("变量命名规范说法正确的是", map03, "B"));choiceQuestionList.add(new ChoiceQuestion("以下()不是合法的标识符", map04, "C"));choiceQuestionList.add(new ChoiceQuestion("表达式(11+3*8)/4%3的值 是", map05, " D"));answerQuestionList.add(new AnswerQuestion("⼩红⻢和⼩⿊⻢⽣的⼩⻢⼏条腿", "4条腿"));answerQuestionList.add(new AnswerQuestion("铁棒打头疼还是⽊棒打头疼", "头最疼"));answerQuestionList.add(new AnswerQuestion("什么床不能睡觉", "⽛床"));answerQuestionList.add(new AnswerQuestion("为什么好⻢不吃回头草", "后⾯的草没了"));//打印当前考生的试卷StringBuilder detail = new StringBuilder("考⽣:" + candidate + "\r\n" + "考号:" + number + "\r\n" + "--------------------------------------------\r\n" + "⼀、选择题" + "\r\n\n");for (int idx = 0; idx < choiceQuestionList.size(); idx++) {detail.append("第").append(idx + 1).append("题:").append(choiceQuestionList.get(idx).getName()).append("\n");Map<String, String> option = choiceQuestionList.get(idx).getOption();option.forEach((k,v)->detail.append(k).append(":").append(option.get(k)).append("\r\n"));detail.append("答 案:").append(choiceQuestionList.get(idx).getKey()).append("\r\n\n");}detail.append("⼆、问答题" + "\r\n\n");for (int idx = 0; idx < answerQuestionList.size(); idx++) {detail.append("第").append(idx + 1).append("题:").append(answerQuestionList.get(idx).getName()).append("\n");detail.append("答 案:").append(answerQuestionList.get(idx).getKey()).append("\r\n\n");}return detail.toString();}
}

选择题类

package com.tansun.goods.prototype_mode;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChoiceQuestion {/*** 题⽬*/private String name;/*** 选项A、B、C、D*/private Map<String, String> option;/*** 答案B*/private String key;
}

问答题

package com.tansun.goods.prototype_mode;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class AnswerQuestion {/*** 问题*/private String name;/*** 答案*/private String key;
}

运行:

package com.tansun.goods;import com.tansun.goods.controller.TestController;
import org.apache.catalina.core.ApplicationContext;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;@SpringBootTest
class GoodsApplicationTests {@Testpublic void test_QuestionBankController() {TestController questionBankController = new TestController();System.out.println(questionBankController.createPaper("花花", "1000001921032"));System.out.println(questionBankController.createPaper("⾖⾖", "1000001921051"));System.out.println(questionBankController.createPaper("⼤宝", "1000001921987"));}}

结果:

考⽣:花花
考号:1000001921032
--------------------------------------------
⼀、选择题第1题:JAVA所定义的版本中不包括
AJAVA2 EE
BJAVA2 Card
CJAVA2 ME
DJAVA2 HE
EJAVA2 SE
答 案:D2题:下列说法正确的是
AJAVA程序的main⽅法必须写在类⾥⾯
BJAVA程序中可以有多个main⽅法
CJAVA程序中类名必须与⽂件名⼀样
DJAVA程序的main⽅法中如果只有⼀条语句,可以不⽤{}(⼤括号)括起来
答 案:A3题:变量命名规范说法正确的是
A:变量由字⺟、下划线、数字、$符号随意组成;
B:变量不能以数字作为开头;
CA和a在java中是同⼀个变量;
D:不同类型的变量,可以起相同的名字;
答 案:B4题:以下()不是合法的标识符
ASTRING
B:x3x;
Cvoid
D:de$f
答 案:C5题:表达式(11+3*8)/4%3的值 是
A31
B0
C1
D2
答 案: D⼆、问答题第1题:⼩红⻢和⼩⿊⻢⽣的⼩⻢⼏条腿
答 案:4条腿第2题:铁棒打头疼还是⽊棒打头疼
答 案:头最疼第3题:什么床不能睡觉
答 案:⽛床第4题:为什么好⻢不吃回头草
答 案:后⾯的草没了考⽣:⾖⾖
考号:1000001921051
--------------------------------------------
⼀、选择题第1题:JAVA所定义的版本中不包括
AJAVA2 EE
BJAVA2 Card
CJAVA2 ME
DJAVA2 HE
EJAVA2 SE
答 案:D2题:下列说法正确的是
AJAVA程序的main⽅法必须写在类⾥⾯
BJAVA程序中可以有多个main⽅法
CJAVA程序中类名必须与⽂件名⼀样
DJAVA程序的main⽅法中如果只有⼀条语句,可以不⽤{}(⼤括号)括起来
答 案:A3题:变量命名规范说法正确的是
A:变量由字⺟、下划线、数字、$符号随意组成;
B:变量不能以数字作为开头;
CA和a在java中是同⼀个变量;
D:不同类型的变量,可以起相同的名字;
答 案:B4题:以下()不是合法的标识符
ASTRING
B:x3x;
Cvoid
D:de$f
答 案:C5题:表达式(11+3*8)/4%3的值 是
A31
B0
C1
D2
答 案: D⼆、问答题第1题:⼩红⻢和⼩⿊⻢⽣的⼩⻢⼏条腿
答 案:4条腿第2题:铁棒打头疼还是⽊棒打头疼
答 案:头最疼第3题:什么床不能睡觉
答 案:⽛床第4题:为什么好⻢不吃回头草
答 案:后⾯的草没了考⽣:⼤宝
考号:1000001921987
--------------------------------------------
⼀、选择题第1题:JAVA所定义的版本中不包括
AJAVA2 EE
BJAVA2 Card
CJAVA2 ME
DJAVA2 HE
EJAVA2 SE
答 案:D2题:下列说法正确的是
AJAVA程序的main⽅法必须写在类⾥⾯
BJAVA程序中可以有多个main⽅法
CJAVA程序中类名必须与⽂件名⼀样
DJAVA程序的main⽅法中如果只有⼀条语句,可以不⽤{}(⼤括号)括起来
答 案:A3题:变量命名规范说法正确的是
A:变量由字⺟、下划线、数字、$符号随意组成;
B:变量不能以数字作为开头;
CA和a在java中是同⼀个变量;
D:不同类型的变量,可以起相同的名字;
答 案:B4题:以下()不是合法的标识符
ASTRING
B:x3x;
Cvoid
D:de$f
答 案:C5题:表达式(11+3*8)/4%3的值 是
A31
B0
C1
D2
答 案: D⼆、问答题第1题:⼩红⻢和⼩⿊⻢⽣的⼩⻢⼏条腿
答 案:4条腿第2题:铁棒打头疼还是⽊棒打头疼
答 案:头最疼第3题:什么床不能睡觉
答 案:⽛床第4题:为什么好⻢不吃回头草
答 案:后⾯的草没了进程已结束,退出代码0

以上就是三位考试的试卷; 花花、 ⾖、⼤宝,每个⼈的试卷内容是⼀样的这没问题,但是三个⼈的题⽬以及选项顺序都是⼀样,就没有达到我们说希望的乱序要求。⽽且以上这样的代码⾮常难扩展,随着题⽬的不断的增加以及乱序功能的补充,都会让这段代码变
得越来越混乱

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

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

相关文章

Ubuntu中变更文件夹的操作权限(chmod使用)

sudo chmod 777 /opt/software/ 777表示所有人都可以修改&#xff0c;读写等操。 sudo chmod 750 /opt/software/ 为了安全起见&#xff0c;上传完毕修改文件夹权限为750,即只有文件夹创建人可以操作 chmod参数说明 第一个数字表示文件所有者的权限 第二个数字表示文件所有…

LangChain - PromptTemplate

文章目录 关于 Prompt关于 PromptTemplate基本创建无变量输入1个变量多变量使用 from_template 自动推断 input_variables 聊天模板使用 from_template 方法构建使用 PromptTemplate 构建 MessagePromptTemplate使用一或多个 MessagePromptTemplates 构建一个 ChatPromptTempla…

pikachu 靶场通关(全)

一.暴力破解 1.1基于表单的暴力破解 1.1.1 漏洞利用 burp抓包&#xff0c;ctrli 添加爆破 根据返回长度得到两个用户 admin 123456 test abc123 1.1.2 源代码分析 文件路径在&#xff1a;vul/burteforce/bf_form.php 通过注释以及说明了&#xff0c;没有验证码也没有其他的…

学习java第三十七天

Spring的优势 1.方便解耦&#xff0c;简化开发&#xff1a;通过spring的ioc容器&#xff0c;将对象间的依赖关系交由Spring进⾏控制&#xff0c;避免硬编码所造成的 过度程序耦合&#xff0c;⽤户也不必再为单例模式类、属性⽂件解析等这些很底层的需求编写代码&#xff0c;可…

上海计算机学会 2024年3月月赛 丙组T4 交易记录(map)

第四题&#xff1a;T4交易记录 标签&#xff1a; m a p map map题意&#xff1a;给定 n n n条股票买入卖出操作&#xff0c;有对应的交易单价 a i a_i ai​和交易数量 b i b_i bi​&#xff0c;分别将多笔买入卖出交易价格相同的进行交易数量合并。买入记录按照交易价格从低到…

【C语言】结构体、枚举、联合(自定义类型)

文章目录 前言一、结构体1.结构体的声明2.结构体的自引用3.结构体变量的定义和初始化4.结构体成员的访问5.结构体内存对齐&#xff08;重点&#xff09;6.#pragma修改默认对齐数7.结构体传参 二、位段1.位段的声明2.位段的内存分配3.位段的跨平台问题 三、枚举四、联合 &#x…

全速前进:2024年MAD(机器学习,人工智能和数据)前景(20000字长文)

THE 2024 MAD (MACHINE LEARNING, ARTIFICIAL INTELLIGENCE & DATA) LANDSCAPE 是FirstMark对数据、分析、机器学习和人工智能生态系统的第十次年度展望和「现状」描述 。 在这个领域的10多年里&#xff0c;事情从来没有像今天这样令人兴奋和充满希望。我们多年来描述的所…

编译Nginx配置QUIC/HTTP3.0

1. 安装BoringSSL sudo apt update sudo apt install -y build-essential ca-certificates zlib1g-dev libpcre3 \ libpcre3-dev tar unzip libssl-dev wget curl git cmake ninja-build mercurial \ libunwind-dev pkg-configgit clone --depth1 https://github.com/google/b…

【蓝桥杯】赛前一周模板

小蜜蜂代码风格的&#xff0c;模块都在&#xff0c;希望能够帮助你吧。 目录 AT24C02存储芯片 DS18B20温度传感器 DS1302 时钟 NE555频率测量 PCF8591 AD PWM波 超声波测距 串口UART 4X4矩阵按键 AT24C02存储芯片 void Write_AT24C02(unsigned char addr,unsigned …

[AIGC] 分布式锁及其实现方式详解与Python代码示例

当你处理分布式系统的并发问题时&#xff0c;你可能需要使用一把全局性的锁来确保在多个进程或线程间顺序执行一些任务。这就是"分布式锁"的概念。在本文中&#xff0c;我们将详细介绍并演示如何在MySQL、Redis以及ZooKeeper中实现分布式锁&#xff0c;并使用Python来…

Rust 实战练习 - 9. 文本编码,URL编码,加密解密

编解码 编程工作中&#xff0c;很复杂的一个环节的就是编解码和多语言。这里只讨论编解码的工作。 目标&#xff1a; 常见文本编码的转换&#xff08;GBK, Shift-JIS, UTF8, Unicode, ASCII)Web中常用的编码常见的加密算法(md5, sha1, HMAC, AES/DES, RSA) encoding/decodi…

Web 后台项目,权限如何定义、设置、使用:菜单权限、按钮权限 ts element-ui-Plus

Web 后台项目&#xff0c;权限如何定义、设置、使用&#xff1a;菜单权限、按钮权限 ts element-ui-Plus 做一个后台管理项目&#xff0c;里面需要用到权限管理。这里说一下权限定义的大概&#xff0c;代码不多&#xff0c;主要讲原理和如何实现它。 一、权限管理的原理 权限…

自动驾驶基础技术-无迹卡尔曼滤波UKF

自动驾驶基础技术-无迹卡尔曼滤波UKF Unscented Kalman Filter是解决非线性卡尔曼滤波的另一种思路&#xff0c;它利用Unscented Transform来解决概率分布非线性变换的问题。UnScented Kalman Filter不需要像Extended Kalman Filter一样计算Jacobin矩阵&#xff0c;在计算量大…

Pixel 手机上连接提示受阻,无法上网-解决方法

命令行中输入 adb shell settings delete global captive_portal_https_urladb shell settings delete global captive_portal_http_url输入服务器信息 adb shell settings put global captive_portal_http_url http://connect.rom.miui.com/generate_204adb shell settings …

从零开始:构建、打包并上传个人前端组件库至私有npm仓库的完整指南

文章目录 一、写组件1、注册全局组件方法2、组件13、组件2 二、测试三、发布1、配置package.json2、生成库包3、配置发布信息4、发布 四、使用1、安装2、使用 五、维护1、维护和更新2、注意事项 一、写组件 确定组件库的需求和功能&#xff1a;在开始构建组件库之前&#xff0c…

基于jenkins+gitlab+docker部署zabbix

背景 我现在已经在一台服务器上部署了jenkins和gitlab&#xff0c;现在有一个场景是需要在服务器上再部署一个zabbix&#xff0c;需要通过jenkins加上gitlab部署&#xff0c;并且要求zabbix是通过docker部署的 前提条件 jenkins、gitlab已完成部署并能正常访问&#xff0c;服…

再探Java为面试赋能(二)Java基础知识(二)反射机制、Lambda表达式、多态

文章目录 前言1.4 反射机制1.4.1 Class对象的获取1.4.2 Class类的方法1.4.3 通过反射机制修改只读类的属性 1.5 Lambda表达式1.5.1 函数式接口1.5.2 Lambda表达式的使用 1.6 多态1.6.1 多态的概念1.6.2 多态的实现条件1.6.3 重载&#xff08;Overload&#xff09;和重写&#x…

大数据之搭建Hive组件

声明&#xff1a;所有软件自行下载&#xff0c;并存放到统一目录中 1.Hive组件的安装配置 1.1实验环境 服务器集群3 个以上节点&#xff0c;节点间网络互通&#xff0c;各节点最低配置&#xff1a;双核 CPU、8GB 内存、100G 硬盘运行环境CentOS 7.4服务和组件完成前面章节实验…

PyCharm详细安装教程与高效使用指南

引言 PyCharm&#xff0c;作为一款广受Python开发者青睐的集成开发环境&#xff08;IDE&#xff09;&#xff0c;以其强大的代码编辑、调试、版本控制以及项目管理功能&#xff0c;极大地提升了开发效率与编程体验。对于初次接触或希望深入掌握PyCharm的用户来说&#xff0c;正…

Spring Boot整合MyBatis-Plus以及实现分页

MyBatis-Plus 是 MyBatis 的一个增强工具包&#xff0c;它在原有的 MyBatis 框架之上提供了更多便捷的功能和增强&#xff0c;有助于简化开发流程、提高开发效率。以下是 MyBatis-Plus 的一些主要特点和功能&#xff1a; CRUD 操作增强&#xff1a; MyBatis-Plus 提供了一套强大…