当前位置: 首页 > 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 的物理学原理与发明历程 经典物理学认为 物体越过势垒,有一阈值能量;粒子能量小于此能量则不能越过,大于此能 量则可以越过。例如骑自行…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...