Builder 生成器模式简介与 C# 示例【创建型2】【设计模式来了_2】
〇、简介
1、什么是生成器模式?
一句话解释:
在构造一个复杂的对象(参数多且有可空类型)时,通过一个统一的构造链路,可选择的配置所需属性值,灵活实现可复用的构造过程。
生成器模式的重心,在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。采用不同的构建实现,产生不同的产品。所以生成器模式都会存在两个部分:整体构建算法、部件的构造和产品的装配。
官方意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
一个比喻:(班级与各科课代表)
每个班级都需要各科课代表,选人条件也会有多个,比如单科成绩名列前茅、课堂表现活跃等,还有些非必要的条件,例如是否开朗等,根据这些条件就可以制定一个标准,对应的就是统一的 IBuilder 接口。不同的科目都可以实现这个接口去生成自己的课代表。
2、优缺点和使用场景
优点:
- 客户端不必知道目标对象内部组成的细节,目标对象本身与目标对象的创建过程解耦,使得相同的创建过程可以创建不同的目标对象;
- 具体创建者可被扩展;
- 更加精细化的操控目标对象的生成过程,根据生成器提供的步骤逐步构建,可以精细化的控制到产品的内部。
缺点:
- 目标对象有很多共同特定,不同的目标对象组成类似,差异不是很多。
适用场景:
- 当创建复杂对象的算法,应该独立于该对象的组成部分,以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
简言之:当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
一、简单的示例代码
如下示例,通过生成器创建一个订单:
// 测试一下
public class Program
{
static void Main(string[] args)
{
OrderBuilder builder = new OrderBuilder();
OrderDirector director = new OrderDirector(builder);
Order order = director.Construct("John Doe", "Product ABC", 2, 10.99m);
Console.WriteLine(order.ToString());
Console.ReadLine();
}
}
// 订单类
public class Order
{
public string CustomerName { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public decimal TotalPrice { get; set; }
public override string ToString() // 重写 ToString() 定义输出格式
{
return $"Customer: {CustomerName}\nProduct: {ProductName}\nQuantity: {Quantity}\nTotal Price: {TotalPrice}";
}
}
// 生成器接口
public interface IBuilder
{
OrderBuilder SetCustomer(string customerName);
OrderBuilder AddProduct(string productName, int quantity, decimal price);
}
// 订单生成器,实现接口 IBuilder
public class OrderBuilder : IBuilder
{
private Order order;
public OrderBuilder()
{
order = new Order();
}
public OrderBuilder SetCustomer(string customerName)
{
order.CustomerName = customerName;
return this;
}
public OrderBuilder AddProduct(string productName, int quantity, decimal price)
{
order.ProductName = productName;
order.Quantity = quantity;
order.TotalPrice = quantity * price;
return this;
}
public Order Build() // 最后返回创建的 Order 对象
{
return order;
}
}
// 订单导向器,完成具体的构建步骤
public class OrderDirector
{
private OrderBuilder builder;
public OrderDirector(OrderBuilder builder)
{
this.builder = builder;
}
public Order Construct(string customerName, string productName, int quantity, decimal price)
{
builder.SetCustomer(customerName)
.AddProduct(productName, quantity, price);
return builder.Build();
}
}
结果输出:

二、生成器模式结构
根据上一章节的示例代码,简单画一个 UML 图,如下:

IBuilder:为创建一个 Order 对象的各个信息而指定抽象接口。
OrderBuilder:实现 IBuilder 的接口以构造和装配该订单的各个部件;定义并明确它所创建的表示;提供一个获取订单的接口。
OrderDirector:构造一个使用 IBuilder 接口的对象。
Order:表示被构造的复杂对象。OrderBuilder 创建该订单的内部表示并定义它的装配过程。包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
三、在 .Net 框架中的实际应用
例如在 WebAPI 项目中的 Program.cs 文件中的主方法 Main(),CreateHostBuilder(args).Build().Run()在 WebHost 构建时采用了生成器模式。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
其生成器接口定义如下,其中 Configure 系列的配置方法均返回构建器接口类,以便在构建时,可以方便的对配置进行连续配置,这也是链式调用的经典场景之一。例如,构建时可以使用CreateHostBuilder(args).ConfigureAppConfiguration(a=>a.builder()).ConfigureServices((builder,s)=>s.register()).Build();,这样感觉像一个流水线机器一样,逐步构建完毕各个部分,最后生成出预制件。
// Microsoft.Extensions.Hosting.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// Microsoft.Extensions.Hosting.IHostBuilder
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public interface IHostBuilder
{
IDictionary<object, object> Properties { get; }
IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate);
IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate);
IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory);
IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate);
IHost Build();
}
四、相关模式
AbstractFactory 与 Builder 相似,因为它也可以创建复杂对象。主要区别是 Builder 模式侧重于一步步构造一个复杂的对象,而 AbstractFactory 侧重于多个系列的产品对象(简单或复杂的)。Builder 在最后一步返回产品,而 AbstractFactory 产品时立即返回的。
另外,Composite 组合模式是用 Builder 生成的。
参考: https://www.cnblogs.com/zhuYears/archive /2012/05/25/2518008.html https://www.cnblogs.com/gaochundong/p/design_pattern_builder.html https://juejin.cn/post/6991323757335805960
Builder 生成器模式简介与 C# 示例【创建型2】【设计模式来了_2】的更多相关文章
- 设计模式03: Builder 生成器模式(创建型模式)
Builder生成器模式(创建型模式) Builder模式缘起假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分富于变化.如果使用最直观的设计方法,每个房屋部分的变化,都将 ...
- C#设计模式之六原型模式(Prototype)【创建型】
一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...
- OOAD-设计模式(三)之创建型设计模式(5种)
前言 前面介绍了OOAD的基础知识,现在我们来详细的说明一下GOF设计模式中的23种模式,希望大家能够学到东西! 一.工厂方法模式(Factory Method) 1.1.工厂方法模式概述 工厂方法模 ...
- 设计模式(二): BUILDER生成器模式 -- 创建型模式
1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式 ...
- Java设计模式-Builder生成器模式
概念: 生成器模式也称之为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,构建与产品分离. UML: Ibuild接口清晰地反映了创建产品Product的流程. 生成器模式涉及4个关键 ...
- 建造者模式(Builder)(生成器模式)(框架化)
建造者模式将一个复杂对象的构建与其表示分离. 将复杂对象进行框架化,将同类的对象编造进同一个制造流程.同类·对象会有一样的框架. 而由于各部分的实现细节有所不同,所生产出来的产品会有所不同.从而有不同 ...
- 设计模式--Builder生成器模式
如果文章中哪里有问题,希望各位大哥大姐指出,小弟十分感激. 正文 什么是生成器模式? 生成器模式就是把生产对象的过程进一步抽取.细化.独立.以往我们生产对象,可能就是在一个小作坊里面从头做到尾.现在用 ...
- 设计模式之简单工厂模式Simple Factory(四创建型)
工厂模式简介. 工厂模式专门负责将大量有共同接口的类实例化 工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类. 工厂模式有三种形态: 1.简单工厂模式Simple Factory ...
- C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了 ...
- C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...
随机推荐
- 5分钟实现调用ChatGPT接口API实现多轮问答
5分钟实现调用ChatGPT接口API完成多轮问答 最近ChatGPT也是火爆异常啊,在亲自使用了几个月之后,我发现这东西是真的好用,实实在在地提高了生产力.那么对于开发人员来说,有时候可能需要在自己 ...
- 用tk.mybaits实现指定字段更新
去年年底的因为业务需要需要在使用tk.mybaits框架的系统中实现指定字段的更新,可是tk.mybaits框架本身并不支持这个功能,我翻遍了CSDN和其他相关的技术相关的网站都没有找到相关的解决 ...
- 民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)
流行天后孙燕姿的音色固然是极好的,但是目前全网都是她的声音复刻,听多了难免会有些审美疲劳,在网络上检索了一圈,还没有发现民谣歌手的音色模型,人就是这样,得不到的永远在骚动,本次我们自己构建训练集,来打 ...
- 2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额。一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10、50
2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额.一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10.50 ...
- Java中synchronized的优化
本文介绍为了实现高效并发,虚拟机对 synchronized 做的一系列的锁优化措施 高效并发是从 JDK5 升级到 JDK6 后一项重要的改进项,HotSpot 虚拟机开发团队在 JDK6 这个版本 ...
- ICANN 2001-Learning to Learn Using Gradient Descent
Key Gradient Descent+LSTM元学习器 解决的主要问题 在之前的机器学习的学习方法中,不会利用到之前的经验,利用到之前经验的"knowledge transfer&quo ...
- JS逆向实战14——猿人学第二题动态cookie
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标网站 https:// ...
- ChatGPT玩法(三):AI玩转PPT
前言 在线免费体验ChatGpt:https://www.topgpt.one 作为许多职场人士的必备工具,PPT制作一直是一个琐碎而费时的任务.但最近我发现了一个非常有用的工具网站,它可以通过人工智 ...
- Nashorn引擎导致metaspace oom
从报错内容很清楚是Metaspace区域oom了 大部分情况下,程序运行中不会出现过多的类加载数量的变动,先导入dump文件检查是否有异常的classLoader或者有异常动态生成的cla ...
- Linux从文件中逐行读取文件名并将匹配的文件复制到指定目录
问题应该算挺常见的但是一句话还挺难说清楚,所以百度特别难搜. 场景就是,有一堆以员工名称命名的文件(名称可能还有字母数字等前后缀),现在给定一个员工清单,需要从这些文件中筛选出员工清单上列出的员工的文 ...