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

常用设计模式全面总结版(JavaKotlin)

这篇文章主要是针对之前博客的下列文章的总结版本:

  • 《设计模式系列学习笔记》
  • 《Kotlin核心编程》笔记:设计模式
  • 【Android知识笔记】FrameWork中的设计模式

主要为了在学习了 Kotlin 之后,将 Java 的设计模式实现与 Kotin 的实现放在一起做一个对比。

一、创建型模式

单例模式(Java)

Double Check Lock + volatile 版本:

public class Singleton { /** 使用 volatile 保证对该变量的写入对另一个线程可见 */private volatile static Singleton mSingleton = null;private Singleton() {}public static Singleton getInstance() {if (mSingleton == null) {synchronized(Singleton.class) {if (mSingleton == null) {mSingleton = new Singleton();}}}return mSingleton;}
}

为什么要 Double Check Lockvolatile,因为 mSingleton = new Singleton() 这一句翻译成字节码指令可能对应多条,它不是一次性完成的原子性操作,会分成三个步骤完成:

  1. 给实例分配内存,
  2. 调用构造函数初始化实例,
  3. 给变量赋值操作。

这三个步骤中后面两步可能发生指令重排序,即顺序为1-3-2,从而导致双重锁定失效,另一个线程同时访问就会拿到一个还没来得及初始化完毕的对象实例,出现问题。

volatile 在这里的主要作用是禁止指令重排序。另外 volatile 还可以保证线程可见性(但不保证原子性)。

静态内部类版本:

public class Singleton {private Singleton(){}/*** 静态内部类,内部类的实例与外部类的实例没有绑定关系,* 只有被调用到时才会加载,从而实现延迟加载*/private static class SingletonHolder {/** 静态初始化器,由 JVM 类加载过程来保证线程安全 */private static Singleton instance = new Singleton();}public static Singleton getInstance() {return SingletonHolder.instance;}
}

注意这个写法,只有getInstance()方法是public的,其他静态内部类及其内部静态变量都是private的。

getInstance方法第一次被调用的时候,会导致JVM 虚拟机加载 SingletonHolder 类,它的静态成员变量得到初始化;从而创建 Singleton 的实例。

补充:JVM加载类的过程:加载 -> 验证 -> 准备 -> 解析 -> 初始化

准备阶段会为SingletonHolder中的静态成员instance赋值为null,在编译时会收集静态赋值语句等组成类构造器<cinit>(),在初始化阶段会执行类构造器来初始化一个类。

触发 JVM 初始化一个类有以下几种情况:

  • 使用new关键字创建对象
  • 访问类的静态成员变量 或 对类的静态成员变量进行赋值
  • 调用类的静态方法
  • 反射调用类时,如 Class.forName()
  • 初始化子类时,会先初始化其父类(如果父类还没有进行过初始化的话)
  • 遇到启动类时,如果一个类被标记为启动类(即包含main方法),虚拟机会先初始化这个主类。
  • 实现带有默认方法的接口的类被初始化时(拥有被default关键字修饰的接口方法的类)
  • 使用 JDK7 新加入的动态语言支持时 MethodHandle

显然当调用Singleton.getInstance() -> SingletonHolder.instance 时,命中上面第 2 条,JVM 就会执行 SingletonHolder 这个类的初始化,然后调用其类构造器<cinit>(),这个时候就会初始化Singleton instance静态成员对象的实例。

在这个过程中, JVM 会保证SingletonHolder这个类的<clinit>()方法被正确的加锁同步,在多线程访问的情况下,只会有一个线程看到这个类的初始化过程,而其他线程是不可见的, 其它线程都需要等待,直到<clinit>()方法执行完毕。所以是线程安全的。

这种方式既保证了线程安全性,又保证了对象的唯一性。并且还是懒加载,只有被调用时才会初始化。

枚举单例:

public enum Singleton {INSTANCE;public void doSomething() {// todo}
}

Android源码中的单例:

  • context.getSystemService(name)context的实现类 ContextImpl 中使用静态的Map对象存储ServiceFecther对象(恶汉)
  • 线程内的单例ThreadLocal,如 ChoreographerLooper 中都使用 ThreadLocal 绑定当前线程,同一个 ThreadLocal 对象在同一个线程内返回的对象是唯一的。
  • 进程内的单例:如 ActivityManager 类的 getService() 方法返回的 IActivityManagerSingleton 单例在进程内唯一。
  • 进程间的单例ServiceManager,不同进程之间内存是隔离的,在进程间共享的单例其实是由binder驱动来保证不同的进程共用同一个对象的。对所有的进程而言,ServiceManager对应同一个binder句柄(通过 0Handle句柄引用),binder句柄处理完不同进程的请求后会转发给ServiceManager所在的进程。

Q:怎样在应用里做一个跨进程的单例?

  • 单例对象类必须实现Parcelable接口,成员变量除了基本数据类型外都必须实现Parcelable接口
  • 通过 AIDL 接口, 拿到远端进程的IBinder对象,再进行 Binder 调用远端接口的业务方法,将单例对象作为参数发布给远端进程
  • 远端进程在业务方法中将接受到单例对象保存下来使用

单例模式(kotlin)

在 kotlin 中 object 类是天生的单例模式。

object Singleton {var x: Int = 2 fun y() { }
}

这个代码翻译成 Java 字节码后发现它其实就是恶汉模式的单例

如果是一个普通类想生成单例,可以使用伴生对象 companion object 来生成:

class Singleton {companion object {var x: Int = 2fun y() { }}
}

如果要实现 Java 中静态内部类版本的单例模式,可以像下面这样写:

class Singleton private constructor() {private object Holder {val INSTANCE = Singleton()}companion object {val instance = Holder.INSTANCE}
}

object不能定义构造函数,但可以定义init块:

object Singleton {var x: Int = 2 fun y(){ }init {//object不能定义构造函数,但可以定义init块}
}

如果要在Java中使用kotlin的单例,最好在成员属性和成员方法上分别加上 @JvmField@JvmStatic注解:

object Singleton {@JvmField var x: Int = 2  @JvmStatic fun y() { } 
}
  • @JvmField 的作用是生成java的静态成员 不会生成gettersetter方法。
  • @JvmStatic 的作用是生成java的静态方法。

object修饰的类内部方法相当于静态方法,但是伪静态,也就是内部会生成一个静态的成员对象,对类的方法调用实际上是调用的内部静态成员对象的方法,只有在方法上添加@JvmStatic才会真正的生成静态方法。

普通kotlin类(非单例)中使用使用JvmFieldJvmStatic

class Foo {//普通类中使用JvmField和JvmStaticcompanion object {@JvmField var x: Int = 2@JvmStatic fun y(){  }}
}

注意,加的注解@JvmField@JvmStatic只针对java平台的可用,其他平台并不可行。

单例的object类仍可以继承类:

object Singleton: Runnable{override fun run() {}
}

工厂方法模式(Java)

  • 定义了一个创建对象的接口,但是由子类来决定要实例化的是哪一个类。工厂方法使类的实例化延迟到子类中。
public abstract class Product {public void method1() {}public abstract void method();
}
public class ConcreteProductA extends Product {@Overridepublic void method2() {//ProductA的业务处理}
}
public class ConcreteProductB extends Product {@Overridepublic void method2() {//ProductB的业务处理}
}
public abstract class Factory {/** * 此方法必须返回一个Product类型的对象*/public abstract <T extends Product> T createProduct(Class<T> c);
}
public class ConcreteFactory extends Factory { @Overridepublic <T extends Product> T createProduct(Class<T> c) {//创建Product的逻辑,这里是直接调用Class的newInstance方法Product product = null;try {product = (Product) Class.forName(c.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T)product;}
}
public class Client {public static void main(String[] args) {Creator creator = new ConcreteCreator();Product productA = creator.createProduct(ConcreteProductA.class);Product productB = creator.createProduct(ConcreteProductB.class);......}
}

简单工厂模式:如果实际当中只需要一个工厂类,那么就不需要抽象的工厂基类,可以把创建产品的方法改为静态方法

public class HumanFactory {@Overridepublic static <T extends Human> T createHuman(Class<T> c) {Human human = null;try {human = (Human) Class.forName(c.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) human;}
}

多个工厂类:在实际当中如果初始化创建对象的过程比较复杂,比如不同的产品可能会设置不同的参数,这个时候创建产品的方法不能共用,所以这时就需要为每一个产品类创建一个工厂类。

可生成单例模式的工厂类:既然工厂方法是用来生产对象的,那么就可以对工厂方法做简单的修改,只返回一个对象,就变成了单例模式。

public class Singleton {//不允许通过new产生对象private Singleton(){}public void doSomething() {//业务处理}
}public class SingletonFactory {private static Singleton singleton;static {try {Class<?> clazz = Class.forName(Singleton.class.getName());//获取无参的构造函数Constructor<?> constructor = clazz.getDeclaredConstructor();//设置无参的构造函数可访问constructor.setAccessible(true);//创建一个实例对象singleton = (Singleton) constructor.newInstance();} catch (Exception e) {e.printStackTrace();}}public static Singleton getSingleton() {return singleton;}
}

可复用缓存的工厂类:如果创建对象的过程比较复杂,或者非常耗时,可以在工厂类内部对已创建的对象进行缓存,以备下次使用。

public class ProductFactory {private static final Map<String, Product> productMap = new HashMap<>();public static synchronized Product createProduct(String type) {Product product = null;//如果缓存中有该对象实例直接使用if (productMap.containsKey(type)) {product = productMap.get(type);} else {if (type.equals("ProductA")) {product = new ConcreteProductA();} else {product = new ConcreteProductB();}//把创建的对象缓存起来productMap.put(type, product);}return product;}
}

Android源码中的工厂方法模式:

  • 集合类的iterator()返回的是一个新的迭代器对象,其实就是一个工厂方法。
  • ActivityonCreate()方法某种角度上可以看作是一个用于创建ContentView的工厂方法,该ContentView用于填充PhoneWindowDecorView的内容区。

抽象工厂模式(Java)

  • 为创建一组相关或依赖的对象提供一个接口,而无需指定它们的具体类。

在这里插入图片描述

/**
* 抽象工厂
*/
public interface AbstractFactory {/**创建A产品家族的产品*/public AbstractProductA createProductA();/**创建B产品家族的产品*/public AbstractProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {//创建一个来自A产品家族的产品return new ProductA1();}@Overridepublic AbstractProductB createProductB() {//创建一个来自B产品家族的产品return new ProductB1();}
}
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {//创建一个来自A产品家族的产品return new ProductA2();}@Overridepublic AbstractProductB createProductB() {//创建一个来自B产品家族的产品return new ProductB2();}
}
/**
* 产品A家族
*/
public abstract class AbstractProductA {/**每个产品共有的方法*/public void shareMethod() {}/**每个产品不同实现的方法*/public abstract void doSomething();
}
public class ProductA1 extends AbstractProductA {@Overridepublic void doSomething() {System.out.println("产品A1的实现方法");}
}
public class ProductA2 extends AbstractProductA {@Overridepublic void doSomething() {System.out.println("产品A2的实现方法");}
}
/**
* 产品B家族
*/
public abstract class AbstractProductB {/**每个产品共有的方法*/public void shareMethod() {}/**每个产品不同实现的方法*/public abstract void doSomething();
}
public class ProductB1 extends AbstractProductB {@Overridepublic void doSomething() {System.out.println("产品B1的实现方法");}
}
public class ProductB2 extends AbstractProductB {@Overridepublic void doSomething() {System.out.println("产品B2的实现方法");}
}
public class Client {public static void main(String[] args) {//创建两个工厂AbstractFactory factory1 = new ConcreteFactory1();AbstractFactory factory2 = new ConcreteFactory2();//使用factory1来创建一组产品,它们来自不同的产品家族AbstractProductA productA1 = factory1.createProductA();AbstractProductB productB1 = factory1.createProductB();//使用factory2来创建一组产品,它们来自不同的产品家族AbstractProductA productA2 = factory2.createProductA();AbstractProductB productB2 = factory2.createProductB();//do something...}
}

抽象工厂模式其实就是每个工厂类是为生产某一类相关性很强的产品类族专门特供的版本

在这里插入图片描述

工厂方法模式(Kotlin)

用单例代替工厂类

我们已经知道 Kotlin 支持用 object 来实现 Java 中的单例模式。所以我们可以使用一个 object 单例来代替一个工厂类。

object ComputerFactory { // 用 object 代替 classfun produce(type: ComputerType): Computer {return when (type) {ComputerType.PC -> PC()ComputerType.Server -> Server()}}
}
fun main() {val compter = ComputerFactory.produce(ComputerType.PC)println(compter.cpu)
}

我们可以通过operator操作符重载invoke方法来代替produce,从而进一步简化表达:

object ComputerFactory {   operator fun invoke(type: ComputerType): Computer {return when (type) {ComputerType.PC -> PC()ComputerType.Server -> Server()}}
}
fun main() {val compter = ComputerFactory(ComputerType.PC)println(compter.cpu)
}

伴生对象创建静态工厂方法

interface Computer {val cpu: Stringcompanion object {operator fun invoke(type: ComputerType): Computer {return when (type) {ComputerType.PC -> PC()ComputerType.Server -> Server()}}}
}class PC(override val cpu: String = "Core") : Computer
class Server(override val cpu: String = "Xeon") : Computerenum class ComputerType { PC, Server }fun main() {val compter = Computer(ComputerType.PC)println(compter.cpu)
}

这样就可以在一个接口类中添加伴生对象的方式来创建静态工厂方法。

伴生对象也可以指定名字:

interface Computer {val cpu: Stringcompanion object Factory {operator fun invoke(type: ComputerType): Computer {return when (type) {ComputerType.PC -> PC()ComputerType.Server -> Server()}}}
}fun main() {val compter = Computer.Factory(ComputerType.PC)println(compter.cpu)
}

为伴生对象添加扩展方法

主要是针对三方类库中无法直接修改源码的类。

fun Computer.Companion.fromCPU(cpu: String): ComputerType? = when(cpu) {"Core" -> ComputerType.PC"Xeon" -> ComputerType.Serverelse -> null
}

指定伴生对象名字的写法:

fun Computer.Factory.fromCPU(cpu: String): ComputerType? = when(cpu) {"Core" -> ComputerType.PC"Xeon" -> ComputerType.Serverelse -> null
}

调用:

fun main() {val type = Computer.fromCPU("Core")println(type)
}

抽象工厂模式(Kotlin)

Kotlin 中的可以使用内联函数 inline + reified 关键字来简化抽象工厂模式:

class Dell: Computer { }
class Asus: Computer { }
class Acer: Computer { }class DellFactory: AbstractFactory() {override fun produce() = Dell()
}
class AsusFactory: AbstractFactory() {override fun produce() = Asus()
}
class AcerFactory: AbstractFactory() {override fun produce() = Acer()
}abstract class AbstractFactory {abstract fun produce(): Computercompanion object {inline operator fun <reified T : Computer> invoke(): AbstractFactory = when(T::class) {Dell::class -> DellFactory()Asus::class -> AsusFactory()Acer::class -> AcerFactory()else -> throw IllegalArgumentException()}}
}fun main() { val dellFactory = AbstractFactory<Dell>()val dell = dellFactory.produce()println(dell)
}

建造者模式(Java)

  • 封装一个产品的构建过程,并允许按步骤构造。
  • 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
public class Robot {private final String code;private final String battery;private final Integer height;private final Integer weight;private Robot(String code, String battery, Integer height, Integer weight) {this.code = code;this.battery = battery;this.height = height;this.weight = weight;}public static class Builder {private final String code;private String battery;private Integer height;private Integer weight;public Builder(String code) {this.code = code;}public Builder setBattery(String battery) {this.battery = battery;return this;}public Builder setHeight(int height) {this.height = height;return this;}public Builder setWeight(int weight) {this.weight = weight;return this;}

相关文章:

常用设计模式全面总结版(JavaKotlin)

这篇文章主要是针对之前博客的下列文章的总结版本: 《设计模式系列学习笔记》《Kotlin核心编程》笔记:设计模式【Android知识笔记】FrameWork中的设计模式主要为了在学习了 Kotlin 之后,将 Java 的设计模式实现与 Kotin 的实现放在一起做一个对比。 一、创建型模式 单例模…...

Docker自建私人云盘系统

Docker自建私人云盘系统。 有个人云盘需求的人&#xff0c;主要需求有这几类&#xff1a; 文件同步、分享需要。 照片、视频同步需要&#xff0c;尤其是全家人都是用的同步。 影视观看需要&#xff08;分为家庭内部、家庭外部&#xff09; 搭建个人网站/博客 云端OFFICE需…...

python replace()方法 指定替换指定字段

replace()方法 使用方法 str.replace(old, new[, max]) Python replace() 方法把字符串中的 old&#xff08;旧字符串&#xff09; 替换成 new(新字符串)&#xff0c;如果指定第三个参数max&#xff0c;则替换不超过 max 次。 示例 #!/usr/bin/pythonstr "this is s…...

【仅供测试】

https://microsoftedge.microsoft.com/addons/detail/%E7%AF%A1%E6%94%B9%E7%8C%B4/iikmkjmpaadaobahmlepeloendndfphd 测试网站&#xff1a; https://www.alipan.com/s/tJ5uzFvp2aF // UserScript // name 阿里云盘助手 // namespace http://tampermonkey.net/ // …...

C#/WPF JSON序列化和反序列化

什么是json json是存储和交换文本信息的方法&#xff0c;类似xml。但是json比xml更小&#xff0c;更快&#xff0c;更易于解析。并且json采用完全独立于语言的文本格式(即不依赖于各种编程语言)&#xff0c;这些特性使json成为理想的数据交换语言。json序列化是指将对象转换成j…...

Java——ArraryList线程不安全

目录 前言一、为什么ArraryList线程不安全&#xff1f;二、具体可以看debug源码后续敬请期待 前言 Java——ArraryList线程不安全 一、为什么ArraryList线程不安全&#xff1f; 因为没有synchronized&#xff0c;这个关键字做线程互斥&#xff0c;没有这个关键字&#xff0c;…...

基于Java SSM框架实现健康管理系统项目【项目源码】

基于java的SSM框架实现健康管理系统演示 JSP技术 JSP是一种跨平台的网页技术&#xff0c;最终实现网页的动态效果&#xff0c;与ASP技术类似&#xff0c;都是在HTML中混合一些程序的相关代码&#xff0c;运用语言引擎来执行代码&#xff0c;JSP能够实现与管理员的交互&#xf…...

PostgreSQL16.1(Windows版本)

1、卸载原有的PostgreSQL &#xfeff; &#xfeff; 点击Next即可。 &#xfeff;&#xfeff; 点击OK即可。 卸载完成。 2、安装 &#xff08;1&#xff09; 前两部直接Next&#xff0c;第二部可以换成自己想要安装的路径。 &#xff08;2&#xff09; 直接点击Next。…...

使用nodejs对接arXiv文献API

GPT4.0国内站点: 海鲸AI-支持GPT(3.5/4.0)&#xff0c;文件分析&#xff0c;AI绘图 要使用 Node.js 对接 arXiv 的 API&#xff0c;你可以使用 axios 库或者 Node.js 的内置 http 模块来发送 HTTP 请求。以下是一个简单的例子&#xff0c;展示了如何使用 axios 来获取 arXiv 上…...

mac 安装pyaudio

直接安装pyaudio时报错 ERROR: Could not build wheels for PyAudio, which is required to install pyproject.toml-based projects需要先安装portaudio&#xff0c;打开终端执行&#xff1a; brew install portaudio再安装pyaudio成功 pip3 install pyaudioportaudio是一个…...

k8s学习 — 各章节重要知识点

k8s学习 — 各章节重要知识点 学习资料k8s版本0 相关命令0.1 yaml配置文件中粘贴内容格式混乱的解决办法0.2 通用命令0.3 Node 相关命令0.4 Pod 相关命令0.5 Deployment 相关命令0.6 Service 相关命令0.7 Namespace 相关命令 1 k8s学习 — 第一章 核心概念1.1 Pod、Node、Servi…...

go slice源码探索(切片、copy、扩容)和go编译源码分析

文章目录 概要一、数据结构二、初始化2.1、字面量2.2、下标截取2.2.1、截取原理 2.3、make关键字2.3.1、编译时 三、复制3.1、copy源码 四、扩容4.1、append源码 五&#xff1a;切片的GC六&#xff1a;切片使用注意事项七&#xff1a;参考 概要 Go语言的切片&#xff08;slice…...

电影“AI化”已成定局,华为、小米转战入局又将带来什么?

从华为、Pika、小米等联合打造电影工业化实验室、到Pika爆火&#xff0c;再到国内首部AI全流程制作《愚公移山》开机……业内频繁的新动态似乎都在预示着2023年国内电影开始加速进入新的制片阶段&#xff0c;国内AI电影热潮即将来袭。 此时以华为为首的底层技术科技企业加入赛…...

小程序for循环中key值的作用?

在小程序的 for 循环中&#xff0c;key 值有两个主要作用&#xff1a; 识别列表项的唯一性&#xff1a;当在列表渲染时使用 for 循环&#xff0c;每个列表项都应该具有一个唯一的 key 值。这个 key 值用于帮助小程序识别每个列表项的唯一性&#xff0c;以便在列表发生变化时进行…...

深入理解Dockerfile —— 筑梦之路

FROM 基础镜像 可以选择现有的镜像&#xff0c;比如centos、debian、apline等&#xff0c;特殊镜像scratch&#xff0c;它是一个空镜像。 如果你以 scratch 为基础镜像的话&#xff0c;意味着你不以任何镜像为基础&#xff0c;接下来所写的指令将作为镜像第一层开始存在。 不…...

Vue3 魔法:轻松删除响应式对象的属性

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃诸葛妙计&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &…...

python命令大全及说明,python命令大全下载

大家好&#xff0c;本文将围绕python命令大全及说明展开说明&#xff0c;python命令大全下载是一个很多人都想弄明白的事情&#xff0c;想搞清楚python简单命令语句需要先了解以下几个事情。 Python有哪些常用但容易忘记的命令&#xff1f; 1 如何忽略报错信息2 Python常见绘图…...

Flink1.17实战教程(第五篇:状态管理)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…...

ES慢查询分析——性能提升6 倍

问题 生产环境频繁报警。查询跨度91天的数据&#xff0c;请求耗时已经来到了30s。报警的阈值为5s。我们期望值是5s内&#xff0c;大于该阈值的请求&#xff0c;我们认为是慢查询。这些慢查询&#xff0c;最终排查&#xff0c;是因为走到了历史集群上。受到了数据迁移的一定影响…...

[NAND Flash 4.3] 闪存的物理学原理_NAND Flash 的读、写、擦工作原理

依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 2.1.3.1 Flash 的物理学原理与发明历程 经典物理学认为 物体越过势垒,有一阈值能量;粒子能量小于此能量则不能越过,大于此能 量则可以越过。例如骑自行…...

海豚调度 Dolphinscheduler-3.2.0/DolphinScheduler-3.1.9 离线部署 伪集群模式

Dolphinscheduler-3.2.0(离线)伪集群模式 一、依赖(前置准备工作) 1.JDK&#xff1a;版本要求 JDK(1.8),安装并配置 JAVA_HOME 环境变量,并将其下的 bin 目录追加到PATH 环境变量中; 2.数据库&#xff1a;PostgreSQL(8.2.15) 或者MySQL(5.7),两者任选其一即可,如 MySQL 则需要…...

4.33 构建onnx结构模型-Expand

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Expand 结点进行分析 方式 方法一…...

LeetCode——1599. 经营摩天轮的最大利润

通过万岁&#xff01;&#xff01;&#xff01; 题目&#xff1a;就是一个摩天轮&#xff0c;一共有4个仓位&#xff0c;一个仓位中最多可以做4个人。然后每次上一个人boardingCost钱&#xff0c;但是我们转动1/4圈&#xff0c;需要的成本是runningCost。然后给我们一个数组cu…...

从 MySQL 的事务 到 锁机制 再到 MVCC

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、事务 1.1 含义 1.2 ACID 二、锁机制 2.1 锁分类 2.2 隔离级别 三、MVCC 3.1 介绍 3.2 隔离级别 3.3 原理 四、总结 前…...

PostGreSQL远程连接

1、找到PostGreSQL安装目录&#xff0c;修改“postgresql.conf”配置文件&#xff08;安装路径\data\postgresql.conf&#xff09;。 若不知道安装目录&#xff0c;则通过服务&#xff0c;找到PostGreSQL运行的任务&#xff0c;右击“属性”可以进行查看安装的目录。 进入该目…...

CSS 缩减顶部动画

<template><!-- mouseenter"startAnimation" 表示在鼠标进入元素时触发 startAnimation 方法。mouseleave"stopAnimation" 表示在鼠标离开元素时触发 stopAnimation 方法。 --><!-- 容器元素 --><div class"container" mou…...

开源掌机是什么?

缘起 最近在学习小游戏的开发&#xff0c;偶然发现有一种叫“掌机”的游戏机&#xff0c;可以玩远古的各类游戏机、街机游戏&#xff01;并且价格都还很便宜。这种神器的东西到底是什么&#xff1f;是如何工作的呢&#xff1f;有市场前景吗&#xff1f;带着这些疑问&#xff0…...

基于Wenet长音频分割降噪识别

Wenet是一个流行的语音处理工具&#xff0c;它专注于长音频的处理&#xff0c;具备分割、降噪和识别功能。它的长音频分割降噪识别功能允许对长时间录制的音频进行分段处理&#xff0c;首先对音频进行分割&#xff0c;将其分解成更小的段落或语音片段。接着进行降噪处理&#x…...

mysql基础-表操作

环境&#xff1a; 管理工具&#xff1a;Navicat 数据库版本&#xff1a;5.7.37 mysql的版本&#xff0c;我们可以通过函数&#xff0c;version()进行查看&#xff0c;本次使用的版本如下&#xff1a; 目录 1.管理工具 1.1创建表 1.2.修改表名 1.3.复制表 1.4.删除表 2…...

MySql——1146 - Table‘mysql.proc‘doesn‘t exit是这个

项目场景&#xff1a; 做自己的小项目需要连接mysql数据库 问题描述 点击数据库时报错 1146 - Table’mysql.proc’doesn’t exit 原因分析&#xff1a; 误删原生的mysql数据库 解决方案&#xff1a; 重新安装装部署mysql就好了 注意不要轻易删除原生的东西...

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 代码下载(1)

本文主要参考&#xff1a; BQ3588C_代码下载 1. 安装依赖工具 安装命令如下&#xff1a; sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flexbison gperf build-essential zip curl zlib1g-dev gcc-multilib g-multiliblibc6-dev-i386 l…...

开源预约挂号平台 - 从0到上线

文章目录 开源预约挂号平台 - 从0到上线演示地址源码地址可以学到的技术前端技术后端技术部署上线开发工具其他技术业务功能 项目讲解前端创建项目 - 安装PNPM - 使用VSCODE - 安装插件首页顶部与底部 - 封装组建 - 使用scss左右布局中间内容部分路由 - vue-routerBANNER- 走马…...

Vue3的proxy

vue3.0中,使用proxy替换了原来遍历对象使用Object.defineProperty方法给属性添加set/get    vue的核心能力之一是监听用户定义的状态变化并响应式刷新DOM   vue2是通过替换状态对象属性的getter和setter来实现的,vue3则通过proxy进行   改为proxy后,可以突破vue当前的…...

Vue Router的介绍与引入

在这里是记录我引入Vue Router的全过程&#xff0c;引入方面也最好先看官方文档 一.介绍 Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;让用 Vue.js 构建单页应用变得轻而易举。功能包括&#xff1a; 嵌套路由映射动态路由选择模块化、基于组件的…...

StratifiedKFold解释和代码实现

StratifiedKFold解释和代码实现 文章目录 一、StratifiedKFold是什么&#xff1f;二、 实验数据设置2.1 实验数据生成代码2.2 代码结果 三、实验代码3.1 实验代码3.2 实验结果3.3 结果解释3.4 数据打乱对这种交叉验证的影响。 四、总结 一、StratifiedKFold是什么&#xff1f; …...

四十八----react实战

一、项目中css模块化管理 1、css-loader 以下可以使用styles.xxx方式使用class是因为使用css-loader配置了module。 import styles from ./index.less export const App(){return <div className={styles.xxx}>hello word</div> }//webpack配置 {test:/\.css$/,u…...

三步实现Java的SM2前端加密后端解密

秦医如毒&#xff0c;无药可解。 话不多说&#xff0c;先上需要用到的js文件下载链接 和 jsp前端代码。 第一步&#xff1a;下载两个必备的js文件—— crypto-js.js、sm2.js 。 它们的下载链接如下↓&#xff08;该网页不魔法上网的话会很卡&#xff0c;毕竟github&#x…...

1分钟带你了解golang(go语言)

Golang&#xff1a;也被称为Go语言&#xff0c;是一种开源的编程语言。由Google的Robert Griesemer、Rob Pike和Ken Thompson于2007年开始设计&#xff0c;2009年11月正式对外发布。&#xff08;被誉为21世纪的C语言&#xff09; 像python一样的优雅&#xff0c;有c一样的性能…...

CSS-4

平面转换 整体认识 div {margin: 100px 0;width: 100px;height: 100px;background-color: pink;/* 过渡效果 */transition: all 1s;}/* 当鼠标悬停到div时&#xff0c;进行平面转换 */div:hover {transform: translate(800px) rotate(360deg) scale(2) skew(180deg);}作用&…...

Python为何适合开发AI项目?

Python在人工智能&#xff08;AI&#xff09;项目中的流行和广泛应用归因于多个因素&#xff0c;其中一些主要原因包括&#xff1a; 1、易学易用&#xff1a; Python语法简洁清晰&#xff0c;易于学习和理解。这使得新手能够更容易上手&#xff0c;并且对于处理复杂的AI算法和…...

总结心得:各设计模式使用场景

单例模式&#xff1a;创建单个对象 工厂模式&#xff1a;创建对象交给工厂完成&#xff0c;当需要创建的对象是一系列相互关联或相互依赖的产品族时 原型模式&#xff1a;克隆对象&#xff0c;避免创建初始化开销 建造者模式&#xff1a;创建一个复杂对象&#xff0c;该对象…...

详解Vue3中的事件监听方式

本文主要介绍Vue3中的事件监听方式。 目录 一、v-on指令二、使用符号简写三、事件修饰符四、动态事件名五、常见的监听事件六、自定义事件 在Vue3中&#xff0c;事件监听的方式与Vue2有一些不同。 下面是Vue3中事件监听方式的详细介绍&#xff1a; 一、v-on指令 Vue3中仍然使…...

Unity关于easySave2 easySave3保存数据的操作;包含EasySave3运行报错的解决

关于easySave2 easySave3保存数据的操作&#xff1b;包含EasySave3运行报错的解决 /// 数据存储路径&#xff08;Easy Save的默认储存位置为&#xff1a;Application.persistentDataPath&#xff0c;为了方便我们可以给它指定储存路径&#xff09; #region 存储数据/*/// /// 存…...

2022年全球软件质量效能大会(QECon上海站)-核心PPT资料下载

一、峰会简介 近年来&#xff0c;以云计算、移动互联网、物联网、工业互联网、人工智能、大数据及区块链等新一代信息技术构建的智能化应用和产品出现爆发式增长&#xff0c;突破了对于软件形态的传统认知&#xff0c;正以各种展现方式诠释着对新型智能软件的定义。这也使得对…...

【python报错】UserWarning: train_labels has been renamed targets

UserWarning: train_labels has been renamed targetswarnings.warn(“train_labels has been renamed targets”) 这是一条 Python 警告信息&#xff0c;它表示 train_labels 这个变量已经被重命名为 targets&#xff0c;在将来的版本中可能会移除 train_labels。因此&#x…...

算法专题四:前缀和

前缀和 一.一维前缀和(模板)&#xff1a;1.思路一&#xff1a;暴力解法2.思路二&#xff1a;前缀和思路 二. 二维前缀和(模板)&#xff1a;1.思路一&#xff1a;构造前缀和数组 三.寻找数组的中心下标&#xff1a;1.思路一&#xff1a;前缀和 四.除自身以外数组的乘积&#xff…...

STM32学习笔记十五:WS2812制作像素游戏屏-飞行射击游戏(5)探索动画之帧动画

本章又是个重要的章节——动画。 动画&#xff0c;本质上时一系列静态的画面连续播放&#xff0c;欺骗人眼产生动画效果。这个原理自打十九世纪电影诞生开始&#xff0c;就从来没变过。 我们的游戏中也需要一些动画效果&#xff0c;比如&#xff0c;被击中时的受伤效果&#…...

期末复习(程序设计)

根据字符出现频率排序 【问题描述】 给定一个字符串 s &#xff0c;根据字符出现的 频率 对其进行降序排序。一个字符出现的频率是它出现在字符串中的次数。 返回已排序的字符串。 频率相同的的字符按ascii值降序排序。 s不包含空格、制表符、换行符等特殊字符。 【输入格…...

html-css-js移动端导航栏底部固定+i18n国际化全局

需求&#xff1a;要做一个移动端的仿照小程序的导航栏页面操作&#xff0c;但是这边加上了i18n国家化&#xff0c;由于页面切换的时候会导致国际化失效&#xff0c;所以写了这篇文章 1.效果 切换页面的时候中英文也会跟着改变&#xff0c;不会导致切换后回到默认的语言 2.实现…...

Ubuntu Linux 入门指南:面向初学者

目录 1. Ubuntu Linux 简介 Ubuntu 的由来 Ubuntu 与其他 Linux 发行版的比较 Debian&#xff1a; Fedora&#xff1a; openSUSE&#xff1a; Arch Linux&#xff1a; Linux Mint&#xff1a; 第二部分&#xff1a;安装 Ubuntu 1. 准备安装 系统需求 创建 Ubuntu 启…...