原型设计模式

4. 原型设计模式

4.1 浅拷贝

在Java编程中,浅拷贝是指在复制对象时,只复制对象的基本数据类型的值引用类型的地址,不复制引用类型指向的对象本身。浅拷贝可以用于一些简单的场景,例如对象的基本属性不包含其他对象的引用类型,或者不需要修改对象引用类型所指向的对象。

以下是几个使用浅拷贝的场景:

  • 原型模式:在创建一个新对象时,如果该对象和已有对象的属性相同,可以使用
    浅拷贝来复制已有对象的属性,而不必重新创建一个新对象。
  • 缓存数据:当需要缓存某些数据时,可以使用浅拷贝来创建缓存对象。如果原始
    对象不再使用,可以直接将其赋值为null,而不必担心缓存对象的引用被同时置
    为null。
  • 复制属性:当需要将一个对象的属性值复制到另一个对象时,可以使用浅拷贝。
    例如,将一个对象的属性值复制到一个DTO(数据传输对象)中,以传递给其他
    系统或服务。

4.1.1 直接赋值实现

我们举一个很简单的例子,使用浅拷贝来复制一个音乐播放列表,以便为用户创建一个新的播放列表,同时保留原始播放列表的内容。

/*** 类描述:歌曲类** @Author crysw* @Version 1.0* @Date 2023/11/27 22:31*/
public class Song {private String title;private String artist;public Song(String title, String artist) {this.title = title;this.artist = artist;}@Overridepublic String toString() {return "Song{" +"title='" + title + '\'' +", artist='" + artist + '\'' +'}';}
}/*** 类描述:播放列表** @Author crysw* @Version 1.0* @Date 2023/11/27 22:33*/
@Data
public class Playlist {private Long id;private String name;private List<Song> songs = new ArrayList<>();public Playlist() {}public void add(Song song) {songs.add(song);}/*** 浅拷贝source的属性值给当前对象** @param source*/public Playlist(Playlist source) {this.id = source.getId();this.name = source.getName();this.songs = source.getSongs();}
}

测试直接赋值实现的浅拷贝

/*** 类描述:原型设计模式测试案例** @Author crysw* @Version 1.0* @Date 2023/11/27 22:35*/
@Slf4j
public class PrototypePatternTest {/*** 测试自定义浅拷贝*/@Testpublic void test() {Playlist playlist = new Playlist();playlist.setId(1L);playlist.setName("周杰伦");playlist.add(new Song("稻香", "周杰伦"));playlist.add(new Song("迷迭香", "周杰伦"));playlist.add(new Song("七里香", "周杰伦"));log.info("before copy,playlist:{}", playlist);// 浅拷贝Playlist favouriteList = new Playlist(playlist);log.info("before copy,favouriteList:{}", playlist);favouriteList.add(new Song("曹操", "林俊杰"));// favouriteList添加了一首song,因为favouriteList#songs就是指向的playlist#songs,所以当favouriteList#songs发生改变,playlist#songs也会随之改变log.info("after copy,playlist:{}", playlist);log.info("after copy,favouriteList:{}", favouriteList);}
}

我们创建了一个原始播放列表,然后使用浅拷贝创建了一个新的播放列表。注意,我们只复制了歌曲列表的引用,而不是歌曲列表本身。这意味着当我们向新播放列表添加歌曲时,原始播放列表的歌曲列表也会受到影响。

4.1.2 clone方法实现

java中给我们提供了Cloneable接口,可以帮助我们很简单的实现浅拷贝:

/*** 类描述:播放列表, Cloneable接口实现浅拷贝, 需要重写clone()方法** @Author crysw* @Version 1.0* @Date 2023/11/27 22:33*/
@Data
public class Playlist2 implements Serializable, Cloneable {private Long id;private String name;private List<Song> songs = new ArrayList<>();public Playlist2() {}public void add(Song song) {songs.add(song);}/*** 浅拷贝** @return* @throws CloneNotSupportedException*/@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}

clone方法实现浅拷贝的测试用例

/*** 测试Cloneable接口实现的浅拷贝** @throws CloneNotSupportedException*/
@Test
public void test2() throws CloneNotSupportedException {Playlist2 playlist = new Playlist2();playlist.setId(1L);playlist.setName("周杰伦");playlist.add(new Song("稻香", "周杰伦"));playlist.add(new Song("迷迭香", "周杰伦"));playlist.add(new Song("七里香", "周杰伦"));log.info("before copy,playlist:{}", playlist);// 浅拷贝Playlist2 favouriteList = (Playlist2) playlist.clone();log.info("before copy,favouriteList:{}", playlist);favouriteList.add(new Song("曹操", "林俊杰"));// favouriteList添加了一首song,因为favouriteList#songs就是指向的playlist#songs,所以当favouriteList#songs发生改变,playlist#songs也会随之改变log.info("after copy,playlist:{}", playlist);log.info("after copy,favouriteList:{}", favouriteList);
}

在选择使用深拷贝还是浅拷贝时,我们需要根据具体场景来决定。如果对象的属性包含引用类型对象且需要修改这些对象的属性时,应该使用深拷贝;如果对象的属性不包含引用类型对象或不需要修改这些对象的属性时,可以使用浅拷贝。

4.2 深拷贝

4.2.1 递归克隆

在电商领域,一个典型的场景是创建复杂的商品促销活动,假设我们有Product、PromotionRule、PromotionEvent类。

  • Product包含商品的基本信息,如名称,价格,库存等;
  • PromotionRule包含促销规则的详细信息,如折扣,优惠券等;
  • PromotionEvent包含促销活动的基本信息,如名称、开始时间、结束时间以及该活动相关的所有促销规则。

为了实现这个案例,我们首先需要定义一些实体类,每个实体类都要实现Cloneable接口:

Product类

/*** 类描述:产品类,实现Cloneable接口用来拷贝** @Author crysw* @Version 1.0* @Date 2023/11/29 23:22*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Cloneable, Serializable {/*** 商品名称*/private String name;/*** 价格*/private double price;/*** 库存*/private int stock;/*** 重写clone方法** @return* @throws CloneNotSupportedException*/@Overrideprotected Product clone() {try {return (Product) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

PromotionRulel类

/*** 类描述:促销规则类,也实现cloneable接口,用来拷贝** @Author crysw* @Version 1.0* @Date 2023/11/29 23:25*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PromotionRule implements Cloneable, Serializable {/*** 促销类型*/private String type;/*** 优惠折扣*/private double discount;/*** 促销产品*/private Product product;/*** 重写clone方法** @return*/@Overrideprotected PromotionRule clone() {try {PromotionRule promotionRule = (PromotionRule) super.clone();// Product是引用类型,需要进行深拷贝Product cloneProduct = product.clone();promotionRule.setProduct(cloneProduct);return promotionRule;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

PromotionEvent类

/*** 类描述:促销活动类,实现cloneable接口,进行拷贝用** @Author crysw* @Version 1.0* @Date 2023/11/29 23:29*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PromotionEvent implements Cloneable {/*** 促销活动名称*/private String name;/*** 促销开始日期*/private String startDate;/*** 促销结束日期*/private String endDate;/*** 促销规则*/private List<PromotionRule> rules;@Overridepublic PromotionEvent clone() {try {PromotionEvent promotionEvent = (PromotionEvent) super.clone();// 引用类型需要进行深拷贝List<PromotionRule> cloneRules = new ArrayList<>();for (PromotionRule rule : this.rules) {PromotionRule cloneRule = rule.clone();cloneRules.add(cloneRule);}promotionEvent.setRules(cloneRules);return promotionEvent;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

已经为每个实体类实现了深拷贝方法。假设我们需要为不同的商品创建相似的促销活动,我们可以使用深拷贝来实现:

/*** 类描述:原型设计模式测试案例** @Author crysw* @Version 1.0* @Date 2023/11/27 22:35*/
@Slf4j
public class PrototypePatternTest {/*** 测试基于Cloneable实现的深拷贝*/@Testpublic void test3() throws ParseException {// 创建原始促销活动PromotionEvent originalEvent = createSamplePromotionEvent();log.info(">>>before,originalEvent:{}", originalEvent);// 创建新的促销活动(克隆对象)PromotionEvent newEvent = originalEvent.clone();newEvent.setName("新的促销活动");// 现在newEvent是originalEvent的一个深拷贝副本,我们可以对它进行修改而不会影响originalEvent// 修改新促销活动的日期newEvent.setStartDate(addDays(newEvent.getStartDate(), 7));newEvent.setEndDate(addDays(newEvent.getEndDate(), 7));log.info(">>>after,originalEvent:{}", originalEvent);log.info(">>>newEvent:{}", newEvent);// 修改新促销活动的部分规则List<PromotionRule> newRules = newEvent.getRules();newRules.get(0).setDiscount(newRules.get(0).getDiscount() * 1.1);// 现在,我们已经成功地复制了一个与原始活动相似但具有不同日期和部分规则的新促销活动。// 可以将新活动应用于其他商品,而原始活动保持不变。}private PromotionEvent createSamplePromotionEvent() throws ParseException {// 创建示例促销活动List<PromotionRule> rules = Arrays.asList(new PromotionRule("折扣", 0.9, new Product("p1", 33.3, 20)),new PromotionRule("满减", 50, new Product("p1", 33.3, 20)));SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");PromotionEvent event = new PromotionEvent("原始促销活动",sdf.format(new Date()),addDays(new Date(), 7),rules);return event;}private String addDays(String date, int days) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Calendar calendar = Calendar.getInstance();calendar.setTime(sdf.parse(date));calendar.add(Calendar.DATE, days);return sdf.format(calendar.getTime());}private String addDays(Date date, int days) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Calendar calendar = Calendar.getInstance();calendar.setTime(date);calendar.add(Calendar.DATE, days);return sdf.format(calendar.getTime());}
}

4.2.2 序列化

对原型对象进行序列化,再对序列化后的二进制流执行反序列化操作,就可以得到一个完完全全相同的对象,这种序列化的方式有很多比如先转为json,在转成内存模型的对象也是可以的。

/*** 测试基于序列化实现的深拷贝*/
@Test
public void test4() throws Exception {PromotionRule promotionRule = new PromotionRule("折扣", 0.9, new Product("p1", 33.3, 20));log.info(">>>before,promotionRule:{}", promotionRule);// 将对象写道字节数组当中ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(promotionRule);// 获取字节数组byte[] bytes = outputStream.toByteArray();// 用输入流读取ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);PromotionRule clonePromotionRule = (PromotionRule) objectInputStream.readObject();// 修改克隆对象的属性,对原对象没有影响clonePromotionRule.setDiscount(0.88);clonePromotionRule.setType("满减");log.info(">>>after,promotionRule:{}", promotionRule);log.info(">>>clonePromotionRule:{}", clonePromotionRule);// 修改原来对象的属性,对深克隆的新对象没有影响promotionRule.setType("大优惠");promotionRule.setDiscount(0.99);log.info(">>>after2,promotionRule:{}", promotionRule);log.info(">>>after,clonePromotionRule:{}", clonePromotionRule);
}

4.3 应用场景

深拷贝在ERP系统中使用非常多。假设我们有一个订单管理系统,其中包含订单、商品和客户等实体类。我们需要将一张订单复制到另一张新订单中,包括订单上的商品以及客户信息,但是新订单的其他信息需要重新填写,例如订单号、订单日期等等。

首先,定义实体类:

/*** 类描述:客户** @Author crysw* @Version 1.0* @Date 2023/12/3 21:47*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer implements Cloneable {private String customerId;private String customerName;private String address;@Overridepublic Customer clone() {try {return (Customer) super.clone();} catch (CloneNotSupportedException e) {return null;}}
}@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Cloneable, Serializable {/*** 商品名称*/private String name;/*** 价格*/private double price;/*** 库存*/private int stock;/*** 重写clone方法** @return* @throws CloneNotSupportedException*/@Overridepublic Product clone() {try {return (Product) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}/*** 类描述:订单** @Author crysw* @Version 1.0* @Date 2023/12/3 21:46*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Cloneable {private String orderId;private Date orderDate;private Customer customer;private List<Product> products;/*** 重写clone方法** @return* @throws CloneNotSupportedException*/@Overrideprotected Order clone() {try {Order cloneOrder = (Order) super.clone();// 引用类型使用深拷贝cloneOrder.setOrderDate((Date) orderDate.clone());cloneOrder.setCustomer(customer.clone());List<Product> cloneProducts = new ArrayList<>();for (Product product : products) {Product cloneProduct = product.clone();cloneProducts.add(cloneProduct);}cloneOrder.setProducts(cloneProducts);return cloneOrder;} catch (CloneNotSupportedException e) {return null;}}
}

已经为每个实体类实现了深拷贝方法,接下来我们可以在复制订单时使用深拷贝:

@Test
public void test5() {// 创建原始订单Order originalOrder = createSampleOrder();// 创建新订单Order newOrder = originalOrder.clone();newOrder.setOrderId("新订单号");newOrder.setOrderDate(new Date());newOrder.setCustomer(new Customer("002", "新客户名称", "新客户地址"));log.info(">>>originalOrder:{}", originalOrder);log.info(">>>newOrder:{}", newOrder);
}private static Order createSampleOrder() {// 创建示例订单Customer customer = new Customer("001", "客户名称", "客户地址");List<Product> products = Arrays.asList(new Product("p1", 33.1, 10),new Product("p2", 33.2, 20),new Product("p3", 33.3, 30));Order order = new Order("订单号", new Date(), customer, products);return order;
}

在这个例子中,我们创建了一个原始订单,并通过深拷贝创建了一个新的订单。然后我们修改了新订单的部分信息,例如订单号、订单日期以及客户信息,但是保留了原始订单上的商品信息。这样我们就可以快速创建一个新订单,并且可以选择保留或修改原始订单上的商品信息。同时原始订单保持不变,不受新订单的影响。

4.4 源码应用

4.4.1 JDK应用

在JDK中,原型设计模式主要应用于那些需要提供对象拷贝功能的类。以下是一些JDK中使用原型设计模式的示例:
java.lang.Cloneable接口:Cloneable接口是一个标记接口,表示一个类的实例可以被克隆。实现了Cloneable接口的类可以通过重写Object类中的clone() 方法来提供对象复制功能。这种方式允许通过复制现有对象来创建新实例,而不是通过构造函数。

public class MyClass implements Cloneable {// ...@Overridepublic MyClass clone() {try {return (MyClass) super.clone();} catch (CloneNotSupportedException e) {throw new AssertionError(); // Can't happen}}
}

Date类实现了Cloneable接口,提供了一个clone() 方法来创建Date对象的副本。可以通过复制现有Date对象来创建新的Date实
例,而不是通过构造函数。

Date original = new Date();
Date copied = (Date) original.clone();

在JDK中,原型设计模式的应用并不非常广泛。然而,在需要快速创建具有相似属性的新对象时,原型设计模式提供CopyOnWriteArrayList, 在我们对集合进行set修改时,它通过克隆技术对原数据进行了克隆,原始版本对象不受影响。

public Object clone() {try {@SuppressWarnings("unchecked")CopyOnWriteArrayList<E> clone = (CopyOnWriteArrayList<E>) super.clone();clone.resetLock();return clone;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError();}
}public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();E oldValue = get(elements, index);if (oldValue != element) {int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len);newElements[index] = element;setArray(newElements);} else {// Not quite a no-op; ensures volatile write semanticssetArray(elements);}return oldValue;} finally {lock.unlock();}
}

4.4.2 Spring应用

在Java的常用框架SSM(Spring、Spring MVC和MyBatis)中,原型设计模式主要应用在Spring框架的Bean管理上。

在Spring框架中,Bean的生命周期可以是单例(Singleton)或原型(Prototype)。当Bean的作用域被定义为原型时,Spring容器会为每个请求创建一个新的Bean实例,而不是在整个应用程序生命周期内共享一个实例。这就是原型设计模式在Spring框架中的应用。例如,在Spring的XML配置文件中,可以将一个Bean的作用域设置为原型:

<bean id="myBean" class="com.example.MyBean" scope="prototype"/>

或者在基于注解的配置中,使用@Scope 注解:

@Configuration
public class AppConfig {@Bean@Scope("prototype")public MyBean myBean() {return new MyBean();}
}

这样,每次从Spring容器中获取myBean 时,都会创建一个新的实例。原型设计模式允许在需要独立实例的场景中有效地管理对象的生命周期,提高性能和资源利用率。Spring中的原型不是使用深拷贝实现的,而是创建的新对象。

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

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

相关文章

振南技术干货集:ChatGPT,现在我做单片机/嵌入式开发已经离不开它了!(2)

注解目录 &#xff08;此文部分内客由 ChatGPT 生成&#xff0c;你分得出来哪些是人写的&#xff0c;哪些是 ChatGPT 生成的吗?&#xff09; 20.1 恐怖的 ChatGPT 2023年ChatGPT有多火?比 TikTok火4 倍都不止!什么是“范式革命”?从石器时代到飞机大炮就是范式革命。AI绘…

C语言速通笔记(1-40)

1&#xff0e;一个 C 语言程序有且只有一个 main 函数&#xff0c;是程序运行的起点。 2&#xff0e;每个 C 语言程序写完后&#xff0c;都是先编译&#xff0e; c 后链接&#xff0e; obj 最后运行&#xff0e;. exe 3.c和&#xff0e; obj 文件是无法运行的&#xff0c;只有…

Python读取栅格遥感影像并加以辐射校正后导出为Excel的一列数据

本文介绍基于Python语言中的gdal模块&#xff0c;读取一景.tif格式的栅格遥感影像文件&#xff0c;提取其中每一个像元的像素数值&#xff0c;对像素值加以计算&#xff08;辐射定标&#xff09;后&#xff0c;再以一列数据的形式将计算后的各像元像素数据保存在一个.csv格式文…

Redis基础知识

目录 一、为什么要用到Redis? 二、Redis 为什么运行比较快&#xff1f; 三、Redis的数据结构 四、Redis可以实现什么功能&#xff1f; 五、Redis 保证数据持久化方式 1、持久化方式主要有2种&#xff1a;RDB 和 AOF 2、RDB和AOF区别&#xff1f; 六、Redis 中的过期删…

IDA常用操作、快捷键总结以及使用技巧

先贴一张官方的图&#xff0c;然后我再总结一下&#xff0c;用的频率比较高的会做一些简单标注 快捷键 F系列【主要是调试状态的处理】 F2 添加/删除断点F4 运行到光标所在位置F5 反汇编F7 单步步入F8 单步跳过F9 持续运行直到输入/断点/结束 shift系列【主要是调出对应的页…

洛谷 P9389 烂柯杯 C++代码

目录 前言 思路点拨 AC代码 结尾 前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;[THUPC 2023 决赛] 烂柯杯 - 洛谷 题目&#xff1a; 乱七八糟一堆文字&#xff0c;展示不下。 思路点拨 思路1&#xff1a;和围棋有关的人&#xff0c;很容易想到柯洁。 思路2&…

【RotorS仿真系列】Ardrone模型介绍

ardrone是rotors仿真框架提供的一款机型&#xff0c;因为该机型与我们实际使用的机型参数相近&#xff0c;所以这里对它的参数做特别整理和记录。 一、模型参数总结 ardrone的gazebo模型如下图所示&#xff1a; 根据ardrone.yaml&#xff0c;其关键参数如下所示&#xff1a…

Project 1: The Game of Hog(CS61A)

&#xff08;第一阶段&#xff09;问题 5a&#xff08;3 分&#xff09; 实现该函数&#xff0c;该函数模拟了完整的 Hog 游戏。球员 交替轮流掷骰子&#xff0c;直到其中一名玩家达到分数。playgoal 您现在可以忽略 Feral Hogs 规则和论点; 您将在问题 5b 中实现它。feral_h…

UC++中的头文件和宏的那些事儿

假定有如下继承自AActor类的.h文件&#xff1a; #pragma once#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MoveRandom.generated.h"UCLASS() class DEMO01_API AMoveRandom : public AActor {GENERATED_BODY()public…

车联网架构设计(一)_消息平台的搭建

车联网是物联网的一个主要应用方向&#xff0c;车辆通过连接车联网平台&#xff0c;实时进行消息的交互&#xff0c;平台可以提供车辆远程控制&#xff0c;故障检测&#xff0c;车路协同等各方面的功能。 我在车联网行业从事了很长时间的技术工作&#xff0c;参与了整个车联网…

树莓派多串口通信

树莓派多串口通信 串口配置串口通信函数分析串口通信示例代码 参考博文1&#xff1a;树莓派 4 UART 多串口配置通信参考博文2&#xff1a;树莓派wiringPi库详解关于树莓派相关其他环境配置可参考&#xff1a;快速上手树莓派关于wiringPi库初始化与IO口开发可参考&#xff1a;树…

深入探索FastAPI单元测试:使用TestClient轻松测试你的API

原文&#xff1a;深入探索FastAPI单元测试&#xff1a;使用TestClient轻松测试你的API-51CTO.COM 当使用FastAPI进行单元测试时&#xff0c;一个重要的工具是TestClient类。TestClient类允许我们模拟对FastAPI应用程序的HTTP请求&#xff0c;并测试应用程序的响应。这使我们能…

调优--学习笔记

1&#xff0c;Presto调优 数据存储格式 1&#xff09;合理设置分区 与Hive类似&#xff0c;Presto会根据元信息读取分区数据&#xff0c;合理的分区能减少Presto数据读取量&#xff0c;提升查询性能。 2&#xff09;使用列式存储 Presto对ORC文件读取做了特定优化&#xff0c…

Qt OpenCV 学习(一):环境搭建

对应版本 Qt 5.15.2OpenCV 3.4.9MinGW 8.1.0 32-bit 1. OpenCV 下载 确保安装 Qt 时勾选了 MinGW 编译器 本文使用 MinGW 编译好的 OpenCV 库&#xff0c;无需自行编译 确保下载的 MinGW 和上述安装 Qt 时勾选的 MinGW 编译器位数一致&#xff0c;此处均为 x86/32-bit下载地址…

《微信小程序开发从入门到实战》学习四十

4.2 云开发JSON数据库 4.2.11 更新数据 使用数据库API更新数据有两种方法&#xff1a;一.将记录局部更新的update方法&#xff1b;二.以替换的方式更新记录的set方法 update方法可以局部更新一个记录或一个集合的多个记录&#xff0c;更新时只有指定字段更新&#xff0c;其他…

电脑连不上wifi,适配器Intel(R)WiFi6 AX201 160MHz遇到与驱动程序或硬件相关问题,连不上wifi,电脑WiFi图标没了

电脑WiFi图标没了&#xff0c;电脑连不上wifi 适配器IntelWiFi6 AX201 160MHz遇到与驱动程序或硬件相关问题应该怎么解决&#xff1f; 方法一&#xff1a;电脑冷重启即可 就是长按那个开机键&#xff0c;然后滑动关机&#xff0c;&#xff0c;&#xff0c;重启&#xff08;我…

智能诊疗体验:整合AI技术的互联网医院小程序开发

在科技化的趋势下&#xff0c;互联网医院小程序的开发变得愈发重要&#xff0c;尤其是通过整合人工智能&#xff08;AI&#xff09;技术&#xff0c;进一步提升了就医的效率。 一、引言 互联网医院小程序其开发目标是提高医疗服务的效率&#xff0c;同时也也提升了用户的就医…

Clickhouse在货品标签场景的应用

背景 在电商场景中&#xff0c;我们经常需要对货品进行打标签的操作&#xff0c;简单来说就是对货品进行各种分类&#xff0c;按照价格段进行分组&#xff0c;此时运营人员就可以通过价格段捞取到满足条件的商品了&#xff0c;本文就来简单看下这个场景如何在clickhouse中实现…

23种设计模式之C++实践(一)

23种设计模式之C++实践 1. 简介2. 基础知识3. 设计模式(一)创建型模式1. 单例模式——确保对象的唯一性1.2 饿汉式单例模式1.3 懒汉式单例模式比较IoDH单例模式总结2. 简单工厂模式——集中式工厂的实现简单工厂模式总结3. 工厂方法模式——多态工厂的实现工厂方法模式总结4.…

【像素画板】游戏地图编辑器-uniapp项目开发流程详解

嘿&#xff0c;用过像素画板没有哦&#xff0c;相信喜欢绘画的小朋友会对它感兴趣呢&#xff0c;用来绘制像素画非常好看&#xff0c;有没有发现&#xff0c;它是可以用来绘制游戏地图的&#xff0c;是不是很好奇&#xff0c;来一起看看吧。 像素画板&#xff0c;也叫像素画的绘…