设计模式(策略,工厂,单例,享元,门面)+模板方法

文章目录

  • 前提
  • 策略模式
    • 思想
    • 实现
    • 如何拓展
  • 模板方法
    • 存在的问题
    • 思想
    • 实现
    • 如何拓展
  • 工厂模式
    • 实现
    • 问题及解决(解耦)
      • 配置文件方式
      • 使用注解
  • 单例模式
    • 实现方式
      • 1,懒汉式(线程不安全)
      • 2,懒汉式(线程安全)
      • 3,饿汉式
      • 4,双重校验锁机制(面)
      • 5,静态内部类
      • 6,枚举
    • 体现
  • 享元模式
  • 门面模式

前提

假设做一个需求,从文件中拿到数据并存在数据库中,文档有多种不同的类型,比如json,excel,csv等等。在做这个去求得在过程中,如何让代码变得优雅,可读性高,耦合度低,易扩展。

策略模式

为解决上述问题,首先想到的是下面的代码

public class XXX {public void export2Db(String filepath) {String type = getFileType(filepath);if ("csv".equals(type)) {// 读取csv文件, 将数据保存到数据库中, 此处省略500行代码} else if ("json".equals(type)) {// 读取json文件, 将数据保存到数据库中, 此处省略500行代码} else if ("excel".equals(type)) {// 读取excel文件, 将数据保存到数据库中, 此处省略500行代码} else {throw new IllegalArgumentException("不支持该类型: " + type);}}
}

这里可以看到有很多问题,比如

  • type使用String类型的魔法值, 没用枚举.
  • 有几个type就if判断几次, 假设新增txt文件类型, 又要修改代码, 拓展性差.
  • 代码核心代码都写到一个方法中, 一些逻辑无法复用, 而且会导致方法代码巨多, 可读性差, 后续也不好维护.

思想

策略模式是多态最好的体现, 也是解决这种标签类的最好的方式之一.

策略模式的定义为: 在策略模式定义了一系列策略类,并将每个具体实现封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改调用端代码。是一种用来解决很多if else的方式.

实现

在本需求中, 需要写一个顶层的策略接口FileExport, 新增 export2Db抽象方法.

然后根据不同类型的导出方式, 编写CsvExport, ExcelExport, JsonExport三个策略类实现FileExport接口.

这里给出类图和具体代码.

public interface FileExport {void export2Db(String filepath);
}
public class CsvExport implements FileExport{@Overridepublic void export2Db(String filepath) {// 读取csv文件, 将数据保存到数据库中, 此处省略具体代码}
}
public class ExcelExport implements FileExport {@Overridepublic void export2Db(String filepath) {// 读取excel文件, 将数据保存到数据库中, 此处省略具体代码}
}
public class JsonExport implements FileExport{@Overridepublic void export2Db(String filepath) {// 读取json文件, 将数据保存到数据库中, 此处省略具体代码}
}

有其他类依赖于我们的策略类, 那么就可以这样使用, 需要哪个直接传入对应的FileExport对象即可.

class XXX {// 注意这里参数类型声明为FileExport接口, 这就意味着可以传入任意的FileExport实现类public static void fileExport2Db(FileExport fileExport, String filepath) {fileExport.export2Db(filepath);}public static void main(String[] args) {FileExport excelExport = new ExcelExport();fileExport2Db(excelExport, "文件路径");
}

如何拓展

使用策略模式后, 如果后续需求变更, 需要拓展其他文件格式导出到数据库, 比如yml文件导出到数据库. 那么我们新增YmlExport类, 实现FileExport即可.

模板方法

存在的问题

那么, 目前的代码就不存在问题了吗? 当然不是, 我们来看策略模式常见的两个问题

  1. 不同实现类中代码重复(靠模板方法解决)
  2. 如果想要根据传入参数动态使用某个策略类, 还是避免不了大量if else

第一个问题:

当我们要实现具体将某中文件数据导出到数据库时, 可以把大致过程划分为以下几步

  1. 检查参数中的filepath是否合法
    • 路径是否不为空
    • 文件是否存在
    • 文件类型是否和对应策略类类型一致
  2. 读取文件数据到一个Java对象中
    • 对数据进行处理,比如去除空格之类的,这里就是简单模拟一下
    • 注意, 有的文件读取后需要处理, 有的不需要,这里假设json文件需要做额外处理, 但是csv和excel文件不需要读取数据后做处理
  3. 保存到数据库中
    • 将处理后的数据转为数据表对应的实体类
    • 使用mybatis/jpa/jdbc等orm工具保存到数据库中

通过上述的过程我们发现,每个策略类的具体实现经历的大体步骤/框架都相同,只有少部分的代码/逻辑不同,如果每个类都自己写自己的具体实现,就会导致大量的重复代码。

第二个问题:

什么是动态使用策略类?简而言之, 就是根据传入的参数, 或者根据某些情况来决定使用哪个策略类来处理.

现在只能传入FileExport类型的参数,如果我要传入String类型的filePath或者其他标识文件类型的参数,就又会导致因判断属于哪个FileExport而产生if-else,代码如下

public class XXX {public void import2Db(String filepath) {String fileType = getFileType(filepath);FileExport fileExport;if ("csv".equals(fileType)) {fileExport = new CsvExport();fileExport.export2Db(filepath);} else if ("json".equals(fileType)) {fileExport = new JsonExport();fileExport.export2Db(filepath);} else if ("excel".equals(fileType)) {fileExport = new ExcelExport();fileExport.export2Db(filepath);} else {throw new IllegalArgumentException("不支持该类型: " + fileType);}}
}

思想

接下来, 我们用模板方法模式来解决第一个问题, 也就是不同实现类中的代码重复问题。

模板方法模式会在抽象类或者接口中定义一个算法的整体流程, 该流程中会调用不同的方法. 这些方法的具体实现交给不同的子类完成. 也就是说它适合整体流程固定, 具体细节不同的场景.

实现

定义一个抽象类来当模板类

  • 具体方法void check(String filepath): 检查filepath是否合法
  • 具体方法 void fileDataExport2Db(FileData fileData): 导出数据到数据库
  • 实现void export2Db(String filepath): 调用以上四个抽象方法来完成文件导出到数据库
  • 抽象方法needProcessData():是否需要进行数据处理
  • 抽象方法 FileData readFile(String filepath): 来读取文件数据
  • 抽象方法 FileData processData(FileData fileData): 来处理数据
public interface FileExport {void export2Db(String filepath);
}
public abstract class AbstractFileExport implements FileExport {@Overridepublic void export2Db(String filepath) {check(filepath);FileData fileData = readFile(filepath);// 钩子函数, 子类决定是否需要对数据进行处理if (needProcessData()) {fileData = processData(fileData);}fileDataExport2Db(fileData);}protected void check(String filepath) {// 检查filepath是否为空if (StrUtil.isBlank(filepath)) {throw new IllegalArgumentException("filepath为空");}// 检查filepath是否存在, 是否为文件File file = new File(filepath);if (!file.exists() || !file.isFile()) {throw new IllegalArgumentException("filepath不存在或者不是文件");}// 检查文件类型是否为子类可以处理的类型 (用了hutool的FileTypeUtil工具)String type = FileTypeUtil.getType(file);if (!Objects.equals(getFileType(), type)) {throw new IllegalArgumentException("文件类型异常: " + type);}}/*** 数据类型转换并保存到数据库, 这是通用操作, 所以写在父类中*/protected void fileDataExport2Db(FileData fileData) {System.out.println("将处理后的数据转为数据表对应的实体类");System.out.println("使用mybatis/jpa/jdbc等orm工具保存到数据库中");}/*** 如果子类要处理数据, needProcessData()返回true, 并重新该方法*/protected FileData processData(FileData fileData) {throw new UnsupportedOperationException();}/*** 获取子类能处理的文件类型, check()方法会用到*/protected abstract String getFileType();/*** 钩子函数, 让子类决定是否需要处理数据*/protected abstract boolean needProcessData();protected abstract FileData readFile(String filepath);
}
public class JsonExport extends AbstractFileExport {private static final String FILE_TYPE = "json";@Overrideprotected String getFileType() {return FILE_TYPE;}@Overrideprotected boolean needProcessData() {return false;}protected FileData readFile(String filepath) {System.out.println("以json方式读取filepath中的文件");System.out.println("将读取后的结果转为通用的FileData类型");return new FileData();}
}

大量重复代码和流程都被抽取到父类中了. 策略模式中出现的代码重复问题就解决了.

如何拓展

和之前类似, 如果后续需求变更, 需要拓展其他文件格式导出到数据库, 比如yml文件导出到数据库. 那么我们新增YmlExport类, 继承AbstractFileExport即可.

由于AbstractFileExport规定了统一流程, 且提供了 check(), fileDataExport2Db()等方法, 所以后续拓展起来代码量也会更少, 更方便.

工厂模式

前面还剩下一个问题,就是根据传入的参数动态的调用。通过工厂+枚举类来实现。

工厂模式就是用来创建对象的,可以根据参数的不同返回不同的实例。

三种工厂模式的区别-CSDN博客

这里使用简单工厂模式

实现

枚举类

@Getter
@AllArgsConstructor
@ToString
public enum FileType {JSON("json"),CSV("csv");private final String type;private static final Map<String, FileType> VALUE_MAP = Arrays.stream(values()).collect(Collectors.toMap(FileType::getType,Function.identity(),(existing, replacement)->replacement));public static FileType stringParseObject(String fileType) {if(!VALUE_MAP.containsKey(fileType)){throw new IllegalArgumentException("不支持的文件类型");}return VALUE_MAP.get(fileType);}
}

工厂类

public class FileExportFactory {private static final Map<FileType, FileExport> CACHE = new HashMap<>();static {CACHE.put(FileType.JSON, new JsonExport());CACHE.put(FileType.CSV, new CsvExport());}public static FileExport getFileExport(FileType fileType) {if (!CACHE.containsKey(fileType)) {throw new IllegalArgumentException("找不到对应类型:" + fileType.getType());}return CACHE.get(fileType);}public static FileExport getFileExport(String type) {FileType fileType = FileType.from(type);return getFileExport(fileType);}
}

问题及解决(解耦)

可以发现,这种情况下如果要增加新的新的文件类型,那么就需要更改FileExportFactory工厂类的代码,违反了OOP原则中的开闭原则(当应用需求发生改变的时候,我们尽量不要修改源代码,可以对其进行扩展,扩展的功能块不会影响到原来的功能块)。

解决方法

spring的解决方法有两种

  • @Component/@Bean,使用注解方式,动态添加新的文件类型
  • spring.factories,使用kv键值对,配置了需要自动装配类的全类名

配置文件方式

在resource文件夹下的yml配置文件中定义需要用到的全类名,然后读取出来。也可以通过反射拿到所有实现FileExport接口的类,然后筛选拿到需要用到的类。

这里是在枚举类中定义好相应的全类名,这样在工厂类中可以直接拿到。理由:实现类很少,操作简便。

枚举类

@Getter
@AllArgsConstructor
@ToString
public enum FileType {JSON("json", "com.luxiya.design.JsonExport"),CSV("csv","com.luxiya.design.CsvExport");private final String type;private final String className;private static final Map<String, FileType> VALUE_MAP = Arrays.stream(values()).collect(Collectors.toMap(FileType::getType,Function.identity(),(existing, replacement)->replacement));public static FileType stringParseObject(String fileType) {if(!VALUE_MAP.containsKey(fileType)){throw new IllegalArgumentException("不支持的文件类型");}return VALUE_MAP.get(fileType);}@SneakyThrowspublic FileExport classNameParseObject() {Class<?> clazz = Class.forName(this.getClassName());return (FileExport) clazz.newInstance();}
}

工厂类

public class FileExportFactory {private static final Map<FileType, FileExport> Cache;static {Cache = Arrays.stream(FileType.values()).map(fileType -> new Pair<>(fileType, fileType.classNameParseObject())).collect(Collectors.toMap(Pair::getKey,Pair::getValue,(existing, replacement)-> replacement));}public static FileExport getFileExport(FileType fileType) {if (!Cache.containsKey(fileType)) {throw new IllegalArgumentException("不支持的文件类型");}return Cache.get(fileType);}public static FileExport getFileExport(String fileType) {FileType fileTypeNew = FileType.stringParseObject(fileType);System.out.println(fileTypeNew);return getFileExport(fileTypeNew);}
}

这样如果新增YmlExport类,增加实现类,然后在枚举类中修改。

使用注解

使用注解实现解耦的流程大概如下

  1. 定义注解,并在相应的类上添加注解。
  2. 通过反射机制拿到添加了注解的类,放入工厂。

定义注解,并在JsonExport和CsvExport类上添加该注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FileExportComponent {
}

工厂类拿到所需类

public class FileExportFactory {private static final Map<FileType, FileExport> Cache;static {Set<Class<?>> classes = ClassUtil.scanPackage("com.luxiya.design", FileExport.class::isAssignableFrom);Cache = classes.stream().filter(ClassUtil::isNormalClass).filter(clazz -> AnnotationUtil.hasAnnotation(clazz, FileExportComponent.class)).map(ReflectUtil::newInstance).map(fileExport -> (FileExport) fileExport).collect(Collectors.toMap(FileExport::getSupportType,Function.identity(),(existing, replacement) -> replacement));}public static FileExport getFileExport(FileType fileType) {if (!Cache.containsKey(fileType)) {throw new IllegalArgumentException("不支持的文件类型");}return Cache.get(fileType);}public static FileExport getFileExport(String fileType) {FileType fileTypeNew = FileType.stringParseObject(fileType);System.out.println(fileTypeNew);return getFileExport(fileTypeNew);}
}

单例模式

保证一个类只有一个实例,并提供一个全局访问他的访问点,避免一个全局使用的类频繁的创建与销毁。

实现方式

1,懒汉式(线程不安全)

**是否 Lazy 初始化:**是

**是否多线程安全:**否

**实现难度:**易

**描述:**这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

public class Singleton {  private static Singleton instance;  private Singleton (){}  public static Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  
}

2,懒汉式(线程安全)

**是否 Lazy 初始化:**是

**是否多线程安全:**是

**实现难度:**易

**描述:**这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。

  • 优点:第一次调用才初始化,避免内存浪费。
  • 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
  • getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)
public class Singleton {  private static Singleton instance;  private Singleton (){}  public static synchronized Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  
}

3,饿汉式

**是否 Lazy 初始化:**否

**是否多线程安全:**是

**实现难度:**易

**描述:**这种方式比较常用,但容易产生垃圾对象。

  • 优点:没有加锁,执行效率会提高。
  • 缺点:类加载时就初始化,浪费内存。
public class Singleton {  private static Singleton instance = new Singleton();  private Singleton (){}  public static Singleton getInstance() {  return instance;  }  
}

4,双重校验锁机制(面)

**是否 Lazy 初始化:**是

**是否多线程安全:**是

**实现难度:**较复杂

**描述:**这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
getInstance() 的性能对应用程序很关键。

    private static volatile Singleton singleton;private Singleton(){}public static Singleton getInstance(){if(singleton == null){synchronized (Singleton.class){if(singleton == null){singleton = new Singleton();}}}return singleton;}

5,静态内部类

**是否 Lazy 初始化:**是

**是否多线程安全:**是

利用 ClassLoader 的特性

  • 类的静态变量在第一次加载类时初始化,JVM 保证这一过程是线程安全的。
  • 静态内部类(如SingletonHolder)不会随外部类(Singleton)的加载而加载,只有在被显式调用时才加载。
public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton() {}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

6,枚举

**是否 Lazy 初始化:**否

**是否多线程安全:**是

**实现难度:**易

**描述:**这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {  INSTANCE;  public void whateverMethod() {  }  
}

体现

上述需求中,其实FileFactory工厂类的Map存储了所有FileExport的实现类,所用代码中用到的都是Map中的实现类,就是单例模式。

且用到的是枚举创建的对象,而且不会被反射和反序列化破坏。

享元模式

通过共享对象来减少系统对象的数量,本质就是缓存对象,降低内存消耗。

享元(Flyweight)的核心思想很简单:如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。

享元模式在Java标准库中有很多应用。我们知道,包装类型如ByteInteger都是不变类,因此,反复创建同一个值相同的包装类型是没有必要的。以Integer为例,如果我们通过Integer.valueOf()这个静态工厂方法创建Integer实例,当传入的int范围在-128~+127之间时,会直接返回缓存的Integer实例:

// 享元模式
public class Main {public static void main(String[] args) throws InterruptedException {Integer n1 = Integer.valueOf(100);Integer n2 = Integer.valueOf(100);System.out.println(n1 == n2); // true}
}

对于Byte来说,因为它一共只有256个状态,所以,通过Byte.valueOf()创建的Byte实例,全部都是缓存对象。

因此,享元模式就是通过工厂方法创建对象,在工厂方法内部,很可能返回缓存的实例,而不是新创建实例,从而实现不可变实例的复用。

其实FileFactory工厂类的Map就是共享对象,运用到了享元模式。

门面模式

一文搞懂设计模式—门面模式-CSDN博客

门面模式(Facade Pattern)也叫做外观模式,是一种结构型设计模式。它提供一个统一的接口,封装了一个或多个子系统的复杂功能,并向客户端提供一个简单的调用方式。通过引入门面,客户端无需直接与子系统交互,而只需要通过门面来与子系统进行通信。

角色职责
门面(Facade)提供统一接口,封装子系统的功能调用,隐藏内部细节。
子系统(Subsystem)实现具体功能的多个模块或类,不直接对外暴露,由门面协调调用。
客户端(Client)通过门面对象间接调用子系统功能,无需依赖具体子系统类。

简单门面类

public class FileExportClient {public static void exportToDb(String filePath){String type = FileTypeUtil.getTypeByPath(filePath);FileExport fileExport = FileExportFactory.getFileExport(type);fileExport.export(filePath);}public static void exportToDb(File file){String filePath = file.getAbsolutePath();exportToDb(filePath);}}

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

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

相关文章

libarchive压缩解压文件

存在中文乱码问题 官网&#xff1a; libarchive - 用于读取和写入 tar、cpio、zip、ISO 和其他存档格式的 C 库和命令行工具 GitHub GitHub源码&#xff1a;Bluewind/libarchive: Multi-format archive and compression library (github.com) 参考&#xff1a; C archive_w…

AutoGPT,自主完成复杂任务

AutoGPT是一个开源的AI Agent项目&#xff0c;它的核心目标是让AI能够自主完成复杂任务&#xff0c;而不仅仅是回答单个问题。简单来说&#xff0c;它让AI具备了"自主思考和行动"的能力。 1. AutoGPT的核心概念 什么是AI Agent&#xff1f; AI Agent&#xff08;智…

lambda、function基础/响应式编程基础

lambda表达式 只要是函数式接口&#xff08;接口内只有一个未实现的方法&#xff0c;可以有其它默认方法&#xff09;&#xff0c;就可以用lambda表达式&#xff0c;也就是快速new一个匿名内部类。 实例化接口的三种方式 继承接口&#xff0c;并实现接口 直接实现匿名内部类 …

OpenTiny 体验官实操活动 | 快速体验 TinyVue 组件库的智能化交互能力

实验简介 通过体验基于标准 MCP 协议的 Web 智能组件库——TinyVue&#xff0c;开发者可以了解 AI 智能体控制 TinyVue 智能组件的各类行为。本次实验主要是在 TinyVue 官网上&#xff0c;开发者能够通过 AI 对话框&#xff0c;以语音或文字方式与网站组件进行互动&#xff0c…

秋招Day15 - Redis - 基础

什么是Redis&#xff1f; Redis是一种基于键值对的NoSQL数据库。 主要的特点是把数据放在内存中&#xff0c;读写速度相比于磁盘会快很多。 对于性能要求很高的场景&#xff0c;比如缓存热点数据&#xff0c;防止接口爆刷&#xff0c;都会用到Redis Redis还支持持久化&…

权限提升-工作流

一、Windows 权限提升 操作阶段 对应工具 说明 系统补丁与漏洞查询 systeminfo、WindowsVulnScan、wesng 提取 KB 补丁号&#xff0c;匹配 CVE 漏洞&#xff08;如 CVE-2020-1054&#xff09; 内核漏洞提权 MSF&#xff08;local_exploit_suggester&#xff09;、CVE 对…

c++手撕线程池

C手撕线程池 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h>#define LL_ADD(item, list) do{ \item->prev NULL; \item->next list; \if…

cocos creator 3.8 - 精品源码 - 六边形消消乐(六边形叠叠乐、六边形堆叠战士)

cocos creator 3.8 - 精品源码 - 六边形消消乐 游戏介绍功能介绍免费体验下载开发环境游戏截图免费体验 游戏介绍 六边形堆叠战士(六边形消消消)是一款脱胎于2048、1010&#xff0c;基于俄罗斯方块的魔性方块达人小游戏&#xff0c;可以多方向多造型消除哦&#xff01; 功能介…

3ds Max高效运行配置核心要素

要保障3ds Max流畅运行&#xff0c;需围绕计算性能、图形处理、数据吞吐三大维度构建硬件体系。不同工作环节对硬件需求存在显著差异&#xff1a; 一、核心组件配置原则 CPU&#xff1a;线程与频率双优化 建模/视口操作&#xff1a;依赖高主频&#xff08;建议≥4.0GHz&#…

实变与泛函题解-心得笔记【16】

文章目录 集合参考文献 集合 参考文献 《实变函数论与泛函分析》

道路交通标志检测数据集-智能地图与导航 交通监控与执法 智慧城市交通管理-2,000 张图像

道路交通标志检测数据集 &#x1f4e6; 已发布目标检测数据集合集&#xff08;持续更新&#xff09;&#x1f6a7; 道路交通标志检测数据集介绍&#x1f4cc; 数据集概览包含类别 &#x1f3af; 应用场景&#x1f5bc; 数据样本展示 YOLOv8 训练实战&#x1f4e6; 1. 环境配置 …

一、jenkins介绍和gitlab部署

一、jenkins介绍 jenkins和持续集成的关系 Jenkins 是实现持续集成&#xff08;CI&#xff09;最流行的自动化工具&#xff0c;它负责自动构建、测试和部署代码&#xff0c;确保团队能频繁且可靠地集成代码变更。 持续集成和敏捷开发的关系 敏捷开发是一种"快速迭代、…

k3s or kubesphere helm安装报错dial tcp 127.0.0.1:8080: connect: connection refused

在安装kubesphere时报错 Error: Kubernetes cluster unreachable: Get "http://localhost:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused helm.go:92: 2025-06-27 15:14:43.30908177 0000 UTC m0.033127135 [debug] Get "http://localh…

使用datafusion和tpchgen-rs进行完整的TPCH 22个查询的基准测试

1.从源码编译bench二进制文件。 下载datafusion源码, 解压到目录&#xff0c;比如/par/dafu&#xff0c; cd /par/dafu/benchmarks export CARGO_INCREMENTAL1 export PATH/par:/par/mold240/bin:$PATH因为mold默认使用并行编译&#xff0c;而这些二进制文件很大&#xff0c;如…

【软考高项论文】论信息系统项目的干系人管理

摘要 在信息系统项目管理里&#xff0c;干系人管理极为关键&#xff0c;它不仅决定项目成败&#xff0c;还对项目进度、质量和成本有着直接影响。本文结合作者2024年6月参与管理的信息系统项目&#xff0c;详细阐述了项目干系人管理的过程&#xff0c;分析了干系人管理与沟通管…

PB应用变为Rust语言方案

从PB(PowerBuilder)迁移到现代开发软件 PowerBuilder(PB)作为早期的快速应用开发工具,曾广泛应用于企业级数据库应用开发。随着技术发展,PB逐渐面临以下挑战,促使企业转向现代开发工具: 技术陈旧与维护困难 PB的架构基于较老的客户端-服务器模式,难以适应云原生、微…

【大模型】Query 改写常见Prompt 模板

下面对常见的几种“Query 改写”Prompt 模板进行中英文对照&#xff0c;并在注释中给出中文说明&#xff0c;帮助中国用户快速理解与使用。 根据调研&#xff0c;企业级 Query 改写模块需要覆盖多种常见场景&#xff0c;包括拼写纠错、中英混合、省略上下文、多义词扩展、专业术…

西门子S7-200 SMART PLC:小型自动化领域的高效之选

在工业自动化领域&#xff0c;小型PLC作为设备控制的核心组件&#xff0c;其性能、灵活性和性价比始终是用户关注的重点。西门子推出的S7-200 SMART可编程控制器&#xff0c;凭借对中国市场需求的精准把握&#xff0c;成为了小型自动化解决方案的标杆产品。本文将从产品亮点、技…

使用iperf3测试网络的方法

深入掌握网络性能测试&#xff1a;iperf3全指南 在网络优化、故障排查和带宽验证中&#xff0c;iperf 是工程师必备的利器。这款开源工具通过模拟数据流&#xff0c;精准测量​​带宽、抖动、丢包率​​等核心指标。本文将结合实战经验&#xff0c;详解iperf的安装、参数配置和…

Level2.11继承

一、继承 #动物# #老虎、狮子、大象 #动物有共性 ##定义一个动物&#xff1a;1.有4条腿&#xff1b;2.陆地上跑&#xff1b;3.需要进食&#xff08;属性能力&#xff09; ##猫&#xff1a;同上&#xff08;继承了动物的属性和能力&#xff09; ##老鼠&#xff1a;同上#Python…