建造者模式:优雅构建复杂对象

article/2025/6/25 7:44:05

引言

在软件开发中,有时我们需要创建一个由多个部分组成的复杂对象,这些部分可能有不同的变体或配置。如果直接在一个构造函数中设置所有参数,代码会变得难以阅读和维护。当对象构建过程复杂,且需要多个步骤时,我们可能会陷入"伸缩式构造函数"的困境,或者创建大量的子类来处理各种组合。

建造者模式(Builder Pattern)提供了一种更优雅的解决方案,它将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式特别适用于需要分步骤创建复杂对象的场景,或者当对象的创建涉及大量参数时。

本文将深入探讨建造者模式的概念、实现方式、应用场景以及优缺点,并通过C#代码示例来展示其实际应用。

文章目录

    • 引言
    • 建造者模式定义
    • 建造者模式的UML类图
    • 建造者模式的组成部分
    • 建造者模式的实现方式
      • 基本实现
      • 使用链式调用的流畅接口
      • 使用指挥者角色
    • 建造者模式的应用场景
      • 复杂对象的创建
      • 参数众多的构造函数
      • 不同表示的构建过程
    • 建造者模式的优缺点
      • 优点
      • 缺点
    • 总结
    • 相关学习资源

建造者模式定义

建造者模式(Builder Pattern)的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

建造者模式属于创建型设计模式,它解决的核心问题包括:

  • 如何构建一个由多个部分组成的复杂对象
  • 如何避免"伸缩式构造函数"的问题
  • 如何允许对象有不同的表示形式
  • 如何分离对象的构建和表示

建造者模式的UML类图

以下是建造者模式的UML类图:

directs
creates
creates
Director
Construct(builder: Builder)
Builder
BuildPartA()
BuildPartB()
BuildPartC()
GetResult()
ConcreteBuilder1
product: Product
BuildPartA()
BuildPartB()
BuildPartC()
GetResult()
ConcreteBuilder2
product: Product
BuildPartA()
BuildPartB()
BuildPartC()
GetResult()
Product
partA: string
partB: string
partC: string
Show()

建造者模式的组成部分

建造者模式包含以下几个核心组件:

  1. 产品(Product)

    • 被构建的复杂对象
    • 包含多个组成部分
    • 具体建造者创建该产品的内部表示并定义装配过程
  2. 抽象建造者(Builder)

    • 声明创建产品各个部分的抽象接口
    • 定义构建产品各个部分的方法
    • 声明返回产品的方法
  3. 具体建造者(Concrete Builder)

    • 实现抽象建造者的接口
    • 定义并跟踪它所创建的产品
    • 提供检索产品的方法
    • 实现构建产品各个部分的细节
  4. 指挥者(Director)

    • 构造一个使用Builder接口的对象
    • 指导构建过程的顺序
    • 隐藏产品是如何组装的细节

客户端代码通常会创建一个具体建造者对象,将其传递给指挥者,然后通过指挥者开始构建过程。当构建过程完成后,客户端从建造者中获取产品。

建造者模式的实现方式

下面通过C#代码示例展示建造者模式的几种实现方式。

基本实现

首先,让我们看一个食品订单系统的例子,实现不同类型的餐点组合:

/// <summary>
/// 产品类 - 表示餐点
/// </summary>
public class Meal
{// 餐点的各个组成部分public string MainCourse { get; set; }public string SideDish { get; set; }public string Drink { get; set; }public string Dessert { get; set; }/// <summary>/// 显示餐点的完整信息/// </summary>public void ShowMeal(){Console.WriteLine("餐点信息:");Console.WriteLine($"- 主菜: {MainCourse ?? "无"}");Console.WriteLine($"- 配菜: {SideDish ?? "无"}");Console.WriteLine($"- 饮料: {Drink ?? "无"}");Console.WriteLine($"- 甜点: {Dessert ?? "无"}");}
}/// <summary>
/// 抽象建造者 - 定义创建餐点各部分的方法
/// </summary>
public interface IMealBuilder
{void BuildMainCourse();void BuildSideDish();void BuildDrink();void BuildDessert();Meal GetMeal();
}/// <summary>
/// 具体建造者 - 健康餐点建造者
/// </summary>
public class HealthyMealBuilder : IMealBuilder
{private Meal _meal = new Meal();public void BuildMainCourse(){_meal.MainCourse = "烤鸡胸肉";}public void BuildSideDish(){_meal.SideDish = "蒸蔬菜";}public void BuildDrink(){_meal.Drink = "矿泉水";}public void BuildDessert(){_meal.Dessert = "水果沙拉";}public Meal GetMeal(){return _meal;}
}/// <summary>
/// 具体建造者 - 快餐建造者
/// </summary>
public class FastFoodMealBuilder : IMealBuilder
{private Meal _meal = new Meal();public void BuildMainCourse(){_meal.MainCourse = "汉堡";}public void BuildSideDish(){_meal.SideDish = "炸薯条";}public void BuildDrink(){_meal.Drink = "可乐";}public void BuildDessert(){_meal.Dessert = "冰淇淋";}public Meal GetMeal(){return _meal;}
}/// <summary>
/// 指挥者 - 负责构建过程
/// </summary>
public class MealDirector
{/// <summary>/// 构建完整餐点/// </summary>/// <param name="builder">餐点建造者</param>/// <returns>构建好的餐点</returns>public Meal ConstructFullMeal(IMealBuilder builder){builder.BuildMainCourse();builder.BuildSideDish();builder.BuildDrink();builder.BuildDessert();return builder.GetMeal();}/// <summary>/// 构建没有甜点的餐点/// </summary>/// <param name="builder">餐点建造者</param>/// <returns>构建好的餐点</returns>public Meal ConstructMealWithoutDessert(IMealBuilder builder){builder.BuildMainCourse();builder.BuildSideDish();builder.BuildDrink();return builder.GetMeal();}
}/// <summary>
/// 客户端代码
/// </summary>
public class Client
{public static void Run(){// 创建指挥者var director = new MealDirector();// 使用健康餐点建造者var healthyBuilder = new HealthyMealBuilder();var healthyMeal = director.ConstructFullMeal(healthyBuilder);Console.WriteLine("健康餐点:");healthyMeal.ShowMeal();// 使用快餐建造者,不含甜点var fastFoodBuilder = new FastFoodMealBuilder();var fastFoodMeal = director.ConstructMealWithoutDessert(fastFoodBuilder);Console.WriteLine("\n快餐餐点(无甜点):");fastFoodMeal.ShowMeal();}
}// 执行客户端代码
Client.Run();/* 输出结果:
健康餐点:
餐点信息:
- 主菜: 烤鸡胸肉
- 配菜: 蒸蔬菜
- 饮料: 矿泉水
- 甜点: 水果沙拉快餐餐点(无甜点):
餐点信息:
- 主菜: 汉堡
- 配菜: 炸薯条
- 饮料: 可乐
- 甜点: 无
*/

在这个基本实现中:

  • Meal 是被构建的产品
  • IMealBuilder 是抽象建造者,定义了构建餐点各部分的方法
  • HealthyMealBuilderFastFoodMealBuilder 是具体建造者,实现了不同风格的餐点创建
  • MealDirector 是指挥者,控制构建过程的顺序
  • 客户端可以选择不同的建造者来创建不同类型的餐点,以及选择不同的构建方式(完整或无甜点)

使用链式调用的流畅接口

建造者模式的一个常见变体是使用方法链(链式调用)创建流畅接口,这在C#中特别常见:

/// <summary>
/// 产品类 - 电子邮件
/// </summary>
public class Email
{// 电子邮件的各个组成部分public string From { get; set; }public string To { get; set; }public string Subject { get; set; }public string Body { get; set; }public List<string> Attachments { get; set; } = new List<string>();public bool IsHtml { get; set; }public string Cc { get; set; }public string Bcc { get; set; }/// <summary>/// 显示电子邮件的内容/// </summary>public void Display(){Console.WriteLine("电子邮件详情:");Console.WriteLine($"发件人: {From}");Console.WriteLine($"收件人: {To}");if (!string.IsNullOrEmpty(Cc)) Console.WriteLine($"抄送: {Cc}");if (!string.IsNullOrEmpty(Bcc)) Console.WriteLine($"密送: {Bcc}");Console.WriteLine($"主题: {Subject}");Console.WriteLine($"正文: {Body}");Console.WriteLine($"格式: {(IsHtml ? "HTML" : "纯文本")}");if (Attachments.Count > 0){Console.WriteLine("附件:");foreach (var attachment in Attachments){Console.WriteLine($"- {attachment}");}}}
}/// <summary>
/// 流畅接口建造者 - 电子邮件建造者
/// </summary>
public class EmailBuilder
{private readonly Email _email = new Email();/// <summary>/// 设置发件人地址/// </summary>/// <param name="from">发件人邮箱地址</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder From(string from){_email.From = from;return this;}/// <summary>/// 设置收件人地址/// </summary>/// <param name="to">收件人邮箱地址</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder To(string to){_email.To = to;return this;}/// <summary>/// 设置邮件主题/// </summary>/// <param name="subject">邮件主题</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder WithSubject(string subject){_email.Subject = subject;return this;}/// <summary>/// 设置邮件正文内容/// </summary>/// <param name="body">邮件内容</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder WithBody(string body){_email.Body = body;return this;}/// <summary>/// 添加附件/// </summary>/// <param name="attachment">附件路径</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder WithAttachment(string attachment){_email.Attachments.Add(attachment);return this;}/// <summary>/// 设置邮件为HTML格式/// </summary>/// <param name="isHtml">是否是HTML格式</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder AsHtml(bool isHtml = true){_email.IsHtml = isHtml;return this;}/// <summary>/// 设置抄送地址/// </summary>/// <param name="cc">抄送邮箱地址</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder WithCc(string cc){_email.Cc = cc;return this;}/// <summary>/// 设置密送地址/// </summary>/// <param name="bcc">密送邮箱地址</param>/// <returns>当前建造者实例以支持链式调用</returns>public EmailBuilder WithBcc(string bcc){_email.Bcc = bcc;return this;}/// <summary>/// 构建电子邮件对象/// </summary>/// <returns>构建好的电子邮件</returns>public Email Build(){// 这里可以添加验证逻辑,例如检查必填字段if (string.IsNullOrEmpty(_email.From))throw new InvalidOperationException("发件人地址不能为空");if (string.IsNullOrEmpty(_email.To))throw new InvalidOperationException("收件人地址不能为空");return _email;}
}// 客户端代码
public class FluentClient
{public static void Run(){// 使用流畅接口创建一封简单邮件var simpleEmail = new EmailBuilder().From("sender@example.com").To("recipient@example.com").WithSubject("问候邮件").WithBody("您好!这是一封测试邮件。").Build();Console.WriteLine("简单邮件:");simpleEmail.Display();// 使用流畅接口创建一封复杂邮件var complexEmail = new EmailBuilder().From("manager@company.com").To("team@company.com").WithCc("supervisor@company.com").WithBcc("records@company.com").WithSubject("项目进度报告").WithBody("<h1>项目进度</h1><p>团队成员们,请查看附件中的项目进度报告。</p>").AsHtml().WithAttachment("progress_report.pdf").WithAttachment("schedule.xlsx").Build();Console.WriteLine("\n复杂邮件:");complexEmail.Display();}
}// 执行客户端代码
FluentClient.Run();/* 输出结果:
简单邮件:
电子邮件详情:
发件人: sender@example.com
收件人: recipient@example.com
主题: 问候邮件
正文: 您好!这是一封测试邮件。
格式: 纯文本复杂邮件:
电子邮件详情:
发件人: manager@company.com
收件人: team@company.com
抄送: supervisor@company.com
密送: records@company.com
主题: 项目进度报告
正文: <h1>项目进度</h1><p>团队成员们,请查看附件中的项目进度报告。</p>
格式: HTML
附件:
- progress_report.pdf
- schedule.xlsx
*/

在这个流畅接口实现中:

  • 每个设置方法返回建造者本身,这使得可以链式调用方法
  • 提供了一种更加简洁、可读性更高的方式来构建复杂对象
  • 允许按需设置各个属性,支持可选参数
  • 在最后调用Build()方法来获取构建好的对象,同时可以进行必要的验证

使用指挥者角色

在一些更复杂的场景中,指挥者(Director)角色可以更好地封装不同的构建过程。下面是一个使用指挥者角色的计算机配置示例:

/// <summary>
/// 产品类 - 计算机
/// </summary>
public class Computer
{// 计算机的各个组件public string CPU { get; set; }public string RAM { get; set; }public string Storage { get; set; }public string GraphicsCard { get; set; }public string Monitor { get; set; }public string OperatingSystem { get; set; }/// <summary>/// 显示计算机配置/// </summary>public void ShowConfiguration(){Console.WriteLine("计算机配置:");Console.WriteLine($"CPU: {CPU ?? "未指定"}");Console.WriteLine($"内存: {RAM ?? "未指定"}");Console.WriteLine($"存储: {Storage ?? "未指定"}");Console.WriteLine($"显卡: {GraphicsCard ?? "未指定"}");Console.WriteLine($"显示器: {Monitor ?? "未指定"}");Console.WriteLine($"操作系统: {OperatingSystem ?? "未指定"}");}
}/// <summary>
/// 抽象建造者 - 计算机建造者
/// </summary>
public interface IComputerBuilder
{void BuildCPU();void BuildRAM();void BuildStorage();void BuildGraphicsCard();void BuildMonitor();void InstallOperatingSystem();Computer GetComputer();
}/// <summary>
/// 具体建造者 - 游戏计算机建造者
/// </summary>
public class GamingComputerBuilder : IComputerBuilder
{private Computer _computer = new Computer();public void BuildCPU(){_computer.CPU = "Intel Core i9-11900K";}public void BuildRAM(){_computer.RAM = "32GB DDR4 3600MHz";}public void BuildStorage(){_computer.Storage = "2TB NVMe SSD";}public void BuildGraphicsCard(){_computer.GraphicsCard = "NVIDIA GeForce RTX 3080";}public void BuildMonitor(){_computer.Monitor = "27英寸 4K 144Hz 游戏显示器";}public void InstallOperatingSystem(){_computer.OperatingSystem = "Windows 11 Pro";}public Computer GetComputer(){return _computer;}
}/// <summary>
/// 具体建造者 - 办公计算机建造者
/// </summary>
public class OfficeComputerBuilder : IComputerBuilder
{private Computer _computer = new Computer();public void BuildCPU(){_computer.CPU = "Intel Core i5-11400";}public void BuildRAM(){_computer.RAM = "16GB DDR4 2666MHz";}public void BuildStorage(){_computer.Storage = "512GB SSD";}public void BuildGraphicsCard(){_computer.GraphicsCard = "集成显卡";}public void BuildMonitor(){_computer.Monitor = "24英寸 1080p 办公显示器";}public void InstallOperatingSystem(){_computer.OperatingSystem = "Windows 10 专业版";}public Computer GetComputer(){return _computer;}
}/// <summary>
/// 具体建造者 - 开发计算机建造者
/// </summary>
public class DeveloperComputerBuilder : IComputerBuilder
{private Computer _computer = new Computer();public void BuildCPU(){_computer.CPU = "AMD Ryzen 9 5900X";}public void BuildRAM(){_computer.RAM = "64GB DDR4 3200MHz";}public void BuildStorage(){_computer.Storage = "1TB NVMe SSD + 2TB HDD";}public void BuildGraphicsCard(){_computer.GraphicsCard = "NVIDIA GeForce RTX 3060";}public void BuildMonitor(){_computer.Monitor = "双 27英寸 4K 专业显示器";}public void InstallOperatingSystem(){_computer.OperatingSystem = "Ubuntu 22.04 LTS";}public Computer GetComputer(){return _computer;}
}/// <summary>
/// 指挥者 - 计算机装配指挥者
/// </summary>
public class ComputerDirector
{/// <summary>/// 构建完整计算机/// </summary>/// <param name="builder">计算机建造者</param>/// <returns>构建好的计算机</returns>public Computer BuildFullComputer(IComputerBuilder builder){builder.BuildCPU();builder.BuildRAM();builder.BuildStorage();builder.BuildGraphicsCard();builder.BuildMonitor();builder.InstallOperatingSystem();return builder.GetComputer();}/// <summary>/// 构建基本计算机(无显卡、基本显示器)/// </summary>/// <param name="builder">计算机建造者</param>/// <returns>构建好的计算机</returns>public Computer BuildBasicComputer(IComputerBuilder builder){builder.BuildCPU();builder.BuildRAM();builder.BuildStorage();builder.InstallOperatingSystem();return builder.GetComputer();}/// <summary>/// 构建无操作系统的计算机/// </summary>/// <param name="builder">计算机建造者</param>/// <returns>构建好的计算机</returns>public Computer BuildComputerWithoutOS(IComputerBuilder builder){builder.BuildCPU();builder.BuildRAM();builder.BuildStorage();builder.BuildGraphicsCard();builder.BuildMonitor();return builder.GetComputer();}
}/// <summary>
/// 客户端代码
/// </summary>
public class DirectorClient
{public static void Run(){// 创建指挥者var director = new ComputerDirector();// 构建游戏计算机(完整配置)var gamingBuilder = new GamingComputerBuilder();var gamingComputer = director.BuildFullComputer(gamingBuilder);Console.WriteLine("游戏计算机配置:");gamingComputer.ShowConfiguration();// 构建基本办公计算机var officeBuilder = new OfficeComputerBuilder();var officeComputer = director.BuildBasicComputer(officeBuilder);Console.WriteLine("\n办公计算机配置:");officeComputer.ShowConfiguration();// 构建无操作系统的开发计算机var developerBuilder = new DeveloperComputerBuilder();var developerComputer = director.BuildComputerWithoutOS(developerBuilder);Console.WriteLine("\n开发计算机配置(无操作系统):");developerComputer.ShowConfiguration();}
}// 执行客户端代码
DirectorClient.Run();/* 输出结果:
游戏计算机配置:
计算机配置:
CPU: Intel Core i9-11900K
内存: 32GB DDR4 3600MHz
存储: 2TB NVMe SSD
显卡: NVIDIA GeForce RTX 3080
显示器: 27英寸 4K 144Hz 游戏显示器
操作系统: Windows 11 Pro办公计算机配置:
计算机配置:
CPU: Intel Core i5-11400
内存: 16GB DDR4 2666MHz
存储: 512GB SSD
显卡: 未指定
显示器: 未指定
操作系统: Windows 10 专业版开发计算机配置(无操作系统):
计算机配置:
CPU: AMD Ryzen 9 5900X
内存: 64GB DDR4 3200MHz
存储: 1TB NVMe SSD + 2TB HDD
显卡: NVIDIA GeForce RTX 3060
显示器: 双 27英寸 4K 专业显示器
操作系统: 未指定
*/

在这个实现中:

  • 指挥者(ComputerDirector)定义了多种不同的构建过程(完整、基本、无操作系统)
  • 具体建造者(GamingComputerBuilderOfficeComputerBuilderDeveloperComputerBuilder)提供了不同的实现方式
  • 客户端可以选择不同的建造者和构建过程的组合,以获得不同配置的计算机
  • 指挥者封装了构建过程,使得客户端代码更加简洁

建造者模式的应用场景

建造者模式适用于以下场景:

建造者模式应用场景
复杂对象的创建
参数众多的构造函数
不同表示的构建过程
分步构建对象
不变性对象的创建

复杂对象的创建

当对象包含多个部分,或者构建需要多个步骤时,建造者模式能够提供清晰的创建过程:

  • 文档生成器(如HTML、PDF、Word文档)
  • 复杂的图形用户界面构建
  • 配置对象的创建
  • 复杂的数据转换和导出

参数众多的构造函数

在需要处理大量可选参数时,建造者模式可以避免"伸缩式构造函数"问题:

  • 避免了使用多个重载构造函数
  • 避免了使用大量参数的构造函数
  • 允许仅设置需要的参数
  • 代码可读性和可维护性更高

不同表示的构建过程

当同一个构建过程可以创建不同表示的对象时,建造者模式特别有用:

  • 不同格式的报告生成
  • 不同风格的UI组件创建
  • 不同平台的代码生成器

建造者模式的优缺点

优点

  1. 分离构建和表示:建造者模式将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

  2. 封装变化:产品的内部结构可以变化,而不会影响客户端代码,因为客户端只与抽象接口交互。

  3. 更好的控制构建过程:建造者模式允许对对象的构建过程进行更精细的控制,特别是在复杂对象的构建中。

  4. 隐藏产品的内部结构:产品的具体细节对客户端是不可见的,客户端只需要与建造者交互。

  5. 提高代码可读性:特别是在使用流畅接口时,构建过程清晰易读。

缺点

  1. 增加类的数量:建造者模式引入了多个新的类,这可能增加系统的复杂性。

  2. 与特定类型绑定:每个具体建造者与特定的产品类型绑定,限制了灵活性。

  3. 不适合简单对象:对于简单对象,使用建造者模式可能是过度设计。

  4. 指挥者可能不总是必要的:在一些实现中,特别是使用流畅接口时,指挥者角色可能是多余的。

  5. 可能导致代码重复:不同的具体建造者可能包含相似的代码。

总结

建造者模式是一种功能强大的创建型设计模式,它允许我们分步骤创建复杂对象,并且可以使用相同的构建过程创建不同的表示。这种模式特别适合处理具有多个组成部分或需要复杂构建过程的对象。

在C#中,建造者模式有多种实现方式,从传统的实现(使用抽象建造者、具体建造者和指挥者),到更现代的流畅接口实现。流畅接口特别适合C#,它提供了一种简洁、可读性强的方式来构建对象。

建造者模式与其他创建型模式(如工厂方法和抽象工厂)相比,更加关注对象的分步构建过程,而不仅仅是简单的实例化。它为控制复杂对象的创建过程提供了更细粒度的方法。

虽然建造者模式增加了代码的复杂性,但在处理复杂对象创建、避免构造函数参数过多或需要不同表示的场景中,这种复杂性是值得的。通过合理应用建造者模式,我们可以创建更加灵活、可维护和可扩展的代码。

相关学习资源

网站资源:

  • Refactoring Guru - Builder Pattern
  • Microsoft Learn - Design Patterns
  • SourceMaking - Builder Design Pattern
  • C# Corner - Builder Design Pattern in C#
  • Dofactory - .NET Design Pattern Framework - Builder

在这里插入图片描述


http://www.hkcw.cn/article/MXoPVAJVBa.shtml

相关文章

JWT 原理与设计上的缺陷及利用

JWT 原理与设计上的缺陷及利用 基本概念 JSON Web Token (JWT)是一个开放标准 ( RFC 7519)&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间以JSON对象的形式安全传输信息。此信息可以验证和信任&#xff0c;因为它是数字签名的。JWT可以使用密钥&…

Jmeter requests

1.Jemter元件和组件 1.1 元件和组件的概念 元件&#xff1a;多个功能相似的的组件的容器&#xff0c;类似于一个工具箱。 组件&#xff1a;实现某个特定功能的实例&#xff0c;类似于工具箱中的螺丝刀&#xff0c;十字扳手... 1.2 作用域和执行顺序 1.2.1 作用域 例子&#…

力扣HOT100之动态规划:300. 最长递增子序列

这道题之前刷代码随想录的时候也刷过&#xff0c;现在又给忘完了。自己尝试着写了一下&#xff0c;发现怎么写都写不对&#xff0c;直接去看视频了。。我自己写的时候的定义是&#xff1a;考虑下标0 ~ i范围内索赔能取到的最长严格递增子序列的长度&#xff0c;后面发现在写递推…

姜老师MBTI课程:ISTP和ISFP

文稿&#xff1a; 今天我们讲两个非常奇怪的人格特质组合。就是如果他又内向又严谨&#xff0c;他还可能P吗&#xff1f;可能愿意去接受风险&#xff0c;去尝鲜探索未知吗&#xff1f;对&#xff0c;咱们今天就讲的是ISP。 首先我们来看ISTP&#xff0c;一个人很内向&#xf…

Cursor奇技淫巧篇(经常更新ing)

Dot files protection &#xff1a;Cursor当开启了Agent模式之后可以自动帮我们写文件&#xff0c;但是一般项目中的一些配置文件&#xff08;通常以.开头的&#xff09;都是非常重要性&#xff0c;为了防止Cursor在运行的过程中自己修改这些文件&#xff0c;导致风险&#xff…

现代数据湖架构全景解析:存储、表格式、计算引擎与元数据服务的协同生态

本文全面剖析现代数据湖架构的核心组件,深入探讨对象存储(OSS/S3)、表格式(Iceberg/Hudi/Delta Lake)、计算引擎(Spark/Flink/Presto)及元数据服务(HMS/Amoro)的协作关系,并提供企业级选型指南。 一、数据湖架构演进与核心价值 数据湖架构演进历程 现代数据湖核心价…

Python训练营打卡Day41(2025.5.31)

知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch归一化层…

MySQL--day10--数据处理之增删改

&#xff08;以下内容全部来自上述课程&#xff09; 增删改 0. 储备工作 #0.储备工作 USE atguigudb; CREATE TABLE IF NOT EXISTS emp1( id INT, name VARCHAR(15), hire_date DATE, salary DOUBLE(10,2) );1. 插入数据 1.1 一条一条添加 # &#xff08;1&#xff09;…

新版智慧景区信息化系统解决方案

该智慧景区信息化系统解决方案以云 + 大数据 + 物联网技术为核心,秉持 “汇聚联合,突显数据隐性价值” 理念,通过数据融合、业务融合、技术融合,构建 “营销、服务、管理” 三位一体模式。方案涵盖智慧票务、智能入园、精准营销、景区管理(如用电安全监测、森林防火、客流…

VAE在扩散模型中的技术实现与应用

VAE在扩散模型中的技术实现与应用 技术概述 在生成式AI领域&#xff0c;VAE&#xff08;变分自编码器&#xff09;与扩散模型的结合代表了当前最先进的技术方向之一。这种结合不仅解决了扩散模型在处理高维数据时的效率问题&#xff0c;还提供了更稳定的训练过程和更好的生成质…

C#中实现两个对象部分相同属性值的复制

在C#中实现两个对象部分相同属性值的复制&#xff0c;可通过以下方案实现&#xff1a; 一、手动赋值&#xff08;基础方案&#xff09; 直接通过属性名逐个赋值&#xff0c;适用于属性较少且明确的情况&#xff1a; // 示例类定义 public class Source { public int Id …

SOC-ESP32S3部分:22-分区表

飞书文档https://x509p6c8to.feishu.cn/wiki/F9PdwnOKhiTRDWk4cr1cIZsvneh 无论是前面我们说到的NVS&#xff0c;还是后面用到的文件系统&#xff0c;他们都必须有存储的载体&#xff0c;例如NVS&#xff0c;我们说过它是存储在Flash中的&#xff0c;那具体是Flash的哪个位置呢…

华为OD机试真题——找出两个整数数组中同时出现的整数(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《找出两个整数数组中同时出…

KWIC—Implicit Invocation

KWIC—Implicit Invocation ✏️ KWIC—Implicit Invocation 文章目录 KWIC—Implicit Invocation&#x1f4dd;KWIC—Implicit Invocation&#x1f9e9;KWIC&#x1f9e9;核心组件&#x1f9e9;ImplementationScheme⚖️ 隐式调用 vs 显式调用对比 &#x1f31f; 总结 &#x…

JWT 入门

一、JWT 概述 1. 扩展(Cookie、Session、Token) 灵魂拷问&#xff1a;为什么你的淘宝账号关闭后&#xff0c;购物车还在&#xff1f;其实这是Cookie 在搞事情。它就像是一种入场券&#xff0c;有该入场券就可以随意进出关卡。但这有个致命的弱点&#xff0c;Cookie是存在客户…

传统液晶瓶颈待破?铁电液晶如何实现显示技术逆袭

一、传统液晶显示&#xff1a;繁华背后的技术枷锁 在消费电子与专业显示领域&#xff0c;液晶技术&#xff08;LCD&#xff09;凭借成熟的产业链和性价比优势&#xff0c;长期占据主流地位。然而&#xff0c;随着 VR/AR、车载显示、高端投影等新兴场景的崛起&#xff0c;传统液…

Mybatis:灵活掌控SQL艺术

在前面的文章中&#xff0c;小编分享了spring中相关的知识&#xff0c;但是没有分享到&#xff0c;如何去更高效操作数据库。 操作数据库传统的方法就是通过JDBC来进行操作。 这个传统方法使用上可谓是够麻烦的 1.首先创建一个数据源对象 2.设置该数据源的属性&#xff08;…

STM32CubeMX定时器配置

STM32CubeMX定时器配置 一&#xff0c;Mode界面1&#xff0c;Slave Mode (从模式)2&#xff0c;Trigger Source (触发源) 三&#xff0c;Channelx&#xff08;通道模式&#xff09;1&#xff0c;Input Capture2&#xff0c;Output Compare3&#xff0c;PWM Generation4&#xf…

可灵2.1 vs Veo 3:AI视频生成谁更胜一筹?

在Google发布Veo 3几天后,可灵显然感受到了压力,发布了即将推出的视频模型系列可灵 2.1的早期体验版。 据我了解,有三种不同的模式: 可灵 2.1 标准模式: 720p分辨率 仅支持图像转视频(生成更快,一致性更好) 5秒视频仍需20积分 可灵 2.1 专业模式: 1080p分辨率 仅在图…

推荐几个不错的AI入门学习视频

引言&#xff1a;昨天推荐了几本AI入门书&#xff08;AI入门书&#xff09;&#xff0c;反响还不错。今天&#xff0c;我再推荐几个不错的AI学习视频&#xff0c;希望对大家有帮助。 网上关于AI的学习视频特别多。有收费的&#xff0c;也有免费的。我今天只推荐免费的。 我们按…