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

C# 设计模式--建造者模式 (Builder Pattern)

定义

建造者模式是一种创建型设计模式,它允许你逐步构建复杂对象,而无需使用多个构造函数或重载。建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。

正确写法

假设我们有一个复杂的 Car 对象,需要逐步构建其各个部分(如引擎、轮胎、颜色等)。

// 产品类
public class Car
{public string Engine { get; set; }public string Tires { get; set; }public string Color { get; set; }public override string ToString(){return $"Car: Engine={Engine}, Tires={Tires}, Color={Color}";}
}// 抽象建造者
public abstract class CarBuilder
{protected Car car;public Car GetCar() => car;public abstract void BuildEngine();public abstract void BuildTires();public abstract void BuildColor();
}// 具体建造者
public class SportsCarBuilder : CarBuilder
{public SportsCarBuilder(){car = new Car();}public override void BuildEngine() => car.Engine = "V8";public override void BuildTires() => car.Tires = "High-performance tires";public override void BuildColor() => car.Color = "Red";
}public class LuxuryCarBuilder : CarBuilder
{public LuxuryCarBuilder(){car = new Car();}public override void BuildEngine() => car.Engine = "V6";public override void BuildTires() => car.Tires = "All-season tires";public override void BuildColor() => car.Color = "Black";
}// 导演类
public class Director
{public void Construct(CarBuilder builder){builder.BuildEngine();builder.BuildTires();builder.BuildColor();}
}// 客户端代码
class Program
{static void Main(string[] args){Director director = new Director();CarBuilder sportsCarBuilder = new SportsCarBuilder();director.Construct(sportsCarBuilder);Car sportsCar = sportsCarBuilder.GetCar();Console.WriteLine(sportsCar);CarBuilder luxuryCarBuilder = new LuxuryCarBuilder();director.Construct(luxuryCarBuilder);Car luxuryCar = luxuryCarBuilder.GetCar();Console.WriteLine(luxuryCar);}
}

类图:

Car
-string Engine
-string Tires
-string Color
+override string ToString()
CarBuilder
-Car car
+Car GetCar()
+abstract void BuildEngine()
+abstract void BuildTires()
+abstract void BuildColor()
SportsCarBuilder
+SportsCarBuilder()
+override void BuildEngine()
+override void BuildTires()
+override void BuildColor()
LuxuryCarBuilder
+LuxuryCarBuilder()
+override void BuildEngine()
+override void BuildTires()
+override void BuildColor()
Director
+void Construct(CarBuilder builder)
Program
+static void Main(string[] args)

解释

  1. 产品类 (Car):定义了汽车的属性(引擎、轮胎、颜色)和一个重写的 ToString 方法,用于显示汽车的详细信息。
  2. 抽象建造者 (CarBuilder):定义了一个受保护的 Car 对象,并提供了获取汽车的方法 GetCar 以及三个抽象方法 BuildEngineBuildTiresBuildColor
  3. 具体建造者 (SportsCarBuilderLuxuryCarBuilder):继承自 CarBuilder,具体实现了构建汽车各个部分的方法。
  4. 导演类 (Director):负责调用具体建造者的构建方法,按照一定的顺序构建汽车。
  5. 客户端代码 (Program):创建了 Director 对象和具体的建造者对象,通过导演类的 Construct 方法构建汽车,并最终获取和显示汽车的信息。

用途

  1. 逐步构建复杂对象:当对象的构建过程复杂且需要多个步骤时,使用建造者模式可以将构建过程分解为多个方法调用。
  2. 分离构建过程和表示:建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
  3. 避免大量的构造函数:避免使用多个构造函数或重载,使代码更加清晰和易于维护。

优点

  1. 封装性好:将对象的构建过程封装在建造者类中,客户端代码不需要关心具体的构建细节。
  2. 代码复用性高:相同的构建过程可以创建不同的表示,提高了代码的复用性。
  3. 易于扩展:增加新的建造者类时,不需要修改现有的代码,符合开闭原则。

缺点

  1. 代码复杂度增加:引入了多个类(抽象建造者、具体建造者、导演类等),系统结构变得更复杂。
  2. 增加类的数量:每增加一个新的产品类型,就需要增加相应的建造者类,类的数量会增加。
  3. 灵活性受限:如果产品的内部表示发生变化,可能需要修改多个建造者类。
    适用场景
  4. 对象构建过程复杂:当对象的构建过程复杂且需要多个步骤时。
  5. 对象的表示多种多样:当需要创建多种不同表示的对象时。
  6. 避免大量的构造函数:当对象的构造函数参数较多且复杂时。

实际开发中的应用

1. 配置文件解析

假设我们需要解析一个复杂的配置文件,并根据配置文件的内容创建相应的对象。
代码如下:

// 配置对象
public class Configuration
{public string Host { get; set; }public int Port { get; set; }public string Username { get; set; }public string Password { get; set; }public override string ToString(){return $"Configuration: Host={Host}, Port={Port}, Username={Username}, Password={Password}";}
}// 抽象建造者
public abstract class ConfigurationBuilder
{protected Configuration configuration;public Configuration GetConfiguration() => configuration;public abstract void BuildHost();public abstract void BuildPort();public abstract void BuildUsername();public abstract void BuildPassword();
}// 具体建造者
public class ProductionConfigBuilder : ConfigurationBuilder
{public ProductionConfigBuilder(){configuration = new Configuration();}public override void BuildHost() => configuration.Host = "prod.example.com";public override void BuildPort() => configuration.Port = 8080;public override void BuildUsername() => configuration.Username = "admin";public override void BuildPassword() => configuration.Password = "securepassword";
}public class DevelopmentConfigBuilder : ConfigurationBuilder
{public DevelopmentConfigBuilder(){configuration = new Configuration();}public override void BuildHost() => configuration.Host = "dev.example.com";public override void BuildPort() => configuration.Port = 8081;public override void BuildUsername() => configuration.Username = "devuser";public override void BuildPassword() => configuration.Password = "devpassword";
}// 导演类
public class ConfigDirector
{public void Construct(ConfigurationBuilder builder){builder.BuildHost();builder.BuildPort();builder.BuildUsername();builder.BuildPassword();}
}// 客户端代码
class Program
{static void Main(string[] args){ConfigDirector director = new ConfigDirector();ConfigurationBuilder productionBuilder = new ProductionConfigBuilder();director.Construct(productionBuilder);Configuration productionConfig = productionBuilder.GetConfiguration();Console.WriteLine(productionConfig);ConfigurationBuilder developmentBuilder = new DevelopmentConfigBuilder();director.Construct(developmentBuilder);Configuration developmentConfig = developmentBuilder.GetConfiguration();Console.WriteLine(developmentConfig);}
}

2. 报告生成

假设我们需要生成不同类型的报告(如 PDF 报告和 HTML 报告),并逐步构建报告的内容。

// 报告对象
public class Report
{public string Title { get; set; }public string Content { get; set; }public string Footer { get; set; }public override string ToString(){return $"Report: Title={Title}, Content={Content}, Footer={Footer}";}
}// 抽象建造者
public abstract class ReportBuilder
{protected Report report;public Report GetReport() => report;public abstract void BuildTitle();public abstract void BuildContent();public abstract void BuildFooter();
}// 具体建造者
public class PdfReportBuilder : ReportBuilder
{public PdfReportBuilder(){report = new Report();}public override void BuildTitle() => report.Title = "PDF Report Title";public override void BuildContent() => report.Content = "This is the content of the PDF report.";public override void BuildFooter() => report.Footer = "Generated by PDF Report Builder";
}public class HtmlReportBuilder : ReportBuilder
{public HtmlReportBuilder(){report = new Report();}public override void BuildTitle() => report.Title = "HTML Report Title";public override void BuildContent() => report.Content = "This is the content of the HTML report.";public override void BuildFooter() => report.Footer = "Generated by HTML Report Builder";
}// 导演类
public class ReportDirector
{public void Construct(ReportBuilder builder){builder.BuildTitle();builder.BuildContent();builder.BuildFooter();}
}// 客户端代码
class Program
{static void Main(string[] args){ReportDirector director = new ReportDirector();ReportBuilder pdfBuilder = new PdfReportBuilder();director.Construct(pdfBuilder);Report pdfReport = pdfBuilder.GetReport();Console.WriteLine(pdfReport);ReportBuilder htmlBuilder = new HtmlReportBuilder();director.Construct(htmlBuilder);Report htmlReport = htmlBuilder.GetReport();Console.WriteLine(htmlReport);}
}

总结

建造者模式 通过将对象的构建过程分解为多个方法调用,使得对象的创建更加灵活和可控。虽然它增加了系统的复杂度,但在需要逐步构建复杂对象的场景中,建造者模式能够显著提高代码的可维护性和扩展性。

在我看来,切碎一点,繁琐一点,微操大神,优势在我

相关文章:

C# 设计模式--建造者模式 (Builder Pattern)

定义 建造者模式是一种创建型设计模式,它允许你逐步构建复杂对象,而无需使用多个构造函数或重载。建造者模式将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。 正确写法 假设我们有一个复杂的 Car 对象,需要…...

leetcode 23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。 输入:lists [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [1->4->5,1->3->4,2->6 ] 将它们合并到一个有序链表中得到。 1->…...

【Redis】深入解析Redis缓存机制:全面掌握缓存更新、穿透、雪崩与击穿的终极指南

文章目录 一、Redis缓存机制概述1.1 Redis缓存的基本原理1.2 常见的Redis缓存应用场景 二、缓存更新机制2.1 缓存更新的策略2.2 示例代码:主动更新缓存 三、缓存穿透3.1 缓存穿透的原因3.2 缓解缓存穿透的方法3.3 示例代码:使用布隆过滤器 四、缓存雪崩4…...

SQL语法——DQL查询

1.查询: 基础查询: select 列名1,列名2 from 表名; # 输入列名为*时为全查 条件查询: select 列名 from 表名 where 条件; #条件中含字符串时为字符串...

云计算.运维.面试题

1、计算机能直接识别的语言( C )。 A、汇编语言 B、自然语言 C、机器语言 D、高级语言 2、应用软件是指( D )。 A、所有能够使用的软件 B、能被各应用单位共同使用的某种软件 C、所有计算机上都应使用的基本软件D、专门为某一应用目的而编制的软件 3、计算机的显示器是一…...

基于vue和vite的计算器

实现思路:1.撰写方案三次迭代(得到方案、项目结构、提问的prompt) 2. 功能实现 3. 优化迭代 计算器项目方案设计(阶段一) 一、项目基本信息 项目名称:基于 Vue 和 Vite 的计算器项目 技术栈: 前…...

《OpenCV:视觉世界的魔法钥匙》

《OpenCV:视觉世界的魔法钥匙》 一、OpenCV 是什么1. 起源与发展支持2. 特点与优势3. 编程语言支持 二、OpenCV 的发展历程1. 重要版本发布时间线2. 版本更新内容 三、OpenCV 的主要功能1. 图像处理2. 特征提取3. 目标检测4. 运动分析5. 人脸识别6. 其他功能 四、Op…...

部署kafka并通过python操作

目录 一、安装JDK1.81、检查服务器是否已安装JDK2、若已安装JDK,进行卸载3、更新yum源4、搜索JDK1.8安装包5、安装JDK1.86、查看是否安装成功7、配置环境变量 二、安装Kafka1、下载并解压kafka部署包至/usr/local/目录2、修改server.properties3、修改/etc/profile4…...

【JAVA】Java高级:数据库监控与调优:SQL调优与执行计划的分析

作为Java开发工程师,理解SQL调优和执行计划的分析是至关重要的。这不仅可以帮助我们提高数据库查询的效率,还能减少系统资源的消耗,提升整体应用的性能。 1. SQL调优的重要性 随着数据量的增加和用户请求的增多,数据库的性能问题…...

【单片机开发】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]

目录 参考资料: 利用 Boot 选择不同的启动方式: 单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM): 1. Cortex-M 内核芯片——启动原理: 1.1. 启动流程: 1.2. 根据单片机的存储器映射和架构图:启动…...

跨库移植 SQL

背景 应用程序可能要基于不同数据库工作,各种数据库的 SQL 语法大体一致,但仍有些差别,结果就要改造这些 SQL,而这事通常只能手工调整,工作量大还容易出错。 完全自动改造 SQL 几乎是无法做到的,毕竟各种…...

(软件测试文档大全)测试计划,测试报告,测试方案,压力测试报告,性能测试,等保测评,安全扫描测试,日常运维检查测试,功能测试等全下载

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.2. 测试环境 4.2.…...

Vue前端开发-路由跳转及带参数跳转

在Vue 3中,由于没有实例化对象this,因此,无法通过this去访问 $route对象,而是通过导入一个名为 useRouter 的方法,执行这个方法后,返回一个路由对象,通过这个路由对象就可以获取到当前路由中的信…...

服务器上安装 Node.js

在服务器上安装 Node.js 的过程根据你使用的操作系统和环境可能会有所不同。以下是一些常见的 Linux 发行版(如 Ubuntu 或 CentOS)上的安装步骤。 在基于 Red Hat/CentOS 的系统上安装 Node.js 设置 EPEL 仓库 如果没有启用 EPEL (Extra Packages for E…...

在阿里云/Linux环境搭建Gitblit服务

在阿里云/Linux环境搭建Gitblit服务 1. 整体描述2. 前期准备3. 安装步骤3.1 下载gitblit3.2 上传gitblit3.3 解压文件3.4 修改文件配置3.5 启动gitblit3.6 安全组配置 4. 总结 1. 整体描述 前段时间买了一个阿里云服务器,2核2G,3M固定带宽的配置&#x…...

MicroBlaze软核开发(二):GPIO

实现功能:使用 MicroBlaze软核,配置GPIO用拨码开关控制LED灯 Vivado版本:2018.3 目录 引言 vivado部分: 一、配置GPIO 二、生成HDL文件编译 SDK部分: 一、导出硬件启动SDK 二、新建应用程序工程 三、编写程序代…...

threejs相机辅助对象cameraHelper

为指定相机创建一个辅助对象,显示这个相机的视锥。 想要在场景里面显示相机的视锥,需要创建两个相机。 举个例子,场景中有个相机A,想要显示相机A的视锥,那么需要一个相机B,把B放在A的后面,两个…...

Luma 视频生成 API 对接说明

Luma 视频生成 API 对接说明 随着 AI 的应用变广,各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的视频。 Luma 是一个专业高质量的视频生成平…...

服务器数据恢复—EVA存储硬盘磁头和盘片损坏离线的数据恢复案例

服务器存储数据恢复环境&故障: 一台HP EVA存储中有23块硬盘,挂接到一台windows server操作系统的服务器。 EVA存储上有三个硬盘指示灯亮黄灯,此刻存储还能正常使用。管理员在更换硬盘的过程中,又出现一块硬盘对应的指示灯亮黄…...

【Python】深入探索Python类型检查:掌握 `typing` 模块的高级用法

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着代码复杂度的增加,类型安全性在现代开发中变得尤为重要。Python自3.5引入类型提示(type hints),为开发者提供了静态类型检查的能力,而typing模块则是这一系统的核心。本篇文章深入研究Python的类型提示及…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...