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); object 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); Order Build(); } // 订单生成器,实现接口 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 IBuilder builder; public OrderDirector(IBuilder 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(); } }
结果输出:
再试着扩展一下:(这里简单举个例子,线上和线下订单区别在是否有购买者用户名)
点击展开示例代码 线上线下订单生成
// 测试一下 public class Program { static void Main(string[] args) { OnlineOrderBuilder onlinebuilder = new OnlineOrderBuilder(); OrderDirector director_on = new OrderDirector(onlinebuilder); director_on.Construct(1, "AutoMation1", "Product ABC", 2, 10.99m, "John Doe"); var order_on = onlinebuilder.Build(); Console.WriteLine($"order_online-{order_on}"); OfflineOrderBuilder offlinebuilder = new OfflineOrderBuilder(); OrderDirector director_off = new OrderDirector(offlinebuilder); director_off.Construct(2, "AutoMation1", "Product 123", 2, 5.6m); var order_off = offlinebuilder.Build(); Console.WriteLine($"order_offline-{order_off}"); Console.ReadLine(); } } // 生成器接口 public interface IBuilder { IBuilder SetProductLine(string customerName); IBuilder AddProduct(string productName, int quantity, decimal price); IBuilder SetUsername(string username); object Build(); } // 线上订单类 public class OnlineOrder { public string ProductLine { get; set; } public string ProductName { get; set; } public int Quantity { get; set; } public decimal TotalPrice { get; set; } public string UserName { get; set; } // 区别就在于线上有用户名 public override string ToString() // 重写 ToString() 定义输出格式 { return $"OnlineOrder-ProductLine: {ProductLine}\nProduct: {ProductName}\nQuantity: {Quantity}\nTotal Price: {TotalPrice}\nUser Name: {UserName} \n"; } } // 线上订单生成器,实现接口 IBuilder public class OnlineOrderBuilder : IBuilder { private OnlineOrder online_order; public OnlineOrderBuilder() { online_order = new OnlineOrder(); } public IBuilder SetProductLine(string productline) { online_order.ProductLine = productline; return this; } public IBuilder AddProduct(string productName, int quantity, decimal price) { online_order.ProductName = productName; online_order.Quantity = quantity; online_order.TotalPrice = quantity * price; return this; } public IBuilder SetUsername(string username) { online_order.UserName = username; return this; } public object Build() // 最后返回创建的 Order 对象 { return online_order; } } // 线下订单类 public class OfflineOrder { public string ProductLine { get; set; } public string ProductName { get; set; } public int Quantity { get; set; } public decimal TotalPrice { get; set; } public override string ToString() // 重写 ToString() 定义输出格式 { return $"OfflineOrder-ProductLine: {ProductLine}\nProduct: {ProductName}\nQuantity: {Quantity}\nTotal Price: {TotalPrice}"; } } // 线下订单生成器,实现接口 IBuilder public class OfflineOrderBuilder : IBuilder { private OfflineOrder offline_order; public OfflineOrderBuilder() { offline_order = new OfflineOrder(); } public IBuilder SetProductLine(string productline) { offline_order.ProductLine = productline; return this; } public IBuilder AddProduct(string productName, int quantity, decimal price) { offline_order.ProductName = productName; offline_order.Quantity = quantity; offline_order.TotalPrice = quantity * price; return this; } public IBuilder SetUsername(string username) { return this; } public object Build() // 最后返回创建的 Order 对象 { return offline_order; } } // 订单导向器,完成具体的构建步骤 public class OrderDirector { private IBuilder builder; public OrderDirector(IBuilder builder) { this.builder = builder; } public void Construct(int ordertype, string productline, string productName, int quantity, decimal price, string username="") { builder.SetProductLine(productline) .AddProduct(productName, quantity, price); switch (ordertype) { case 1: OperationOnlineOrder(builder, username); break; case 2: OperationOffOrder(builder); break; } } public IBuilder OperationOnlineOrder(IBuilder builder, string username) { return builder.SetUsername(username); } public IBuilder OperationOffOrder(IBuilder builder) { return builder; } }
结果输出:
二、生成器模式结构
根据上一章节的示例代码,简单画一个 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

本文来自博客园,作者:橙子家,欢迎微信扫码关注博主【橙子家czzj】,有任何疑问欢迎沟通,共同成长!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步