建造者模式
将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。(就是一个
复杂的大对象,里面有一些小对象,建造者模式就是实现接口或者虚方法,实例化这些小对象,然
后再将整体的大对象返回出去。)
组成模块
1、抽象建造者(Builder):为创建一个对象的各个部件指定抽象接口,以规范产品对象的各个组
成部分。
2、具体建造者(ConcreteBuilder ):(1)实现Builder的接口以构造和装配该对象的各个部件。即
实现抽象建造者角色Builder的方法。(2)构造一个使用Builder接口的对象即在指导者的调用下创
建产品实例。
3、指导者(Director):调用具体建造者角色以创建产品对象的各个部分。指导者并没有涉及具体
产品类的信息,真正拥有具体产品的信息是具体建造者对象。它只负责保证对象各部分完整创建或
按某种顺序创建。
4、产品角色(Product):建造中的对象,有哪些属性或组件。
Demo
1、产品角色
public class CPU
{
/// <summary>
/// CPU型号
/// </summary>
public string ModelNumber { get; set; }
}
public class Mouse
{
/// <summary>
/// 鼠标蓝牙型号
/// </summary>
public string BluetoothModel { get; set; }
}
public class Display
{
/// <summary>
/// 显示屏分辨率
/// </summary>
public string Resolution { get; set; }
}
public class Computer
{
public CPU Cpu { get; set; }
public Mouse Mouse_ { get; set; }
public Display Display_ { get; set; }
}
2、构建抽象建造者
public interface IBuilderComputer
{
/// <summary>
/// 组装CPU
/// </summary>
void BuilderCPU();
/// <summary>
/// 组装鼠标
/// </summary>
void BuilderMouse();
/// <summary>
/// 组装显示屏
/// </summary>
void BuilderDisplay();
/// <summary>
/// 返回组装成功的电脑
/// </summary>
/// <returns></returns>
Computer BuilderComputer();
}
3、具体构建者
//具体构造者
public class ConcreteBuilder : Builder
{
private Computer computer = new Computer();
public Computer BuilderComputer()
{
return computer;
}
public void BuilderCPU()
{
computer.Cpu = new CPU(){ ModelNumber = "酷睿i7-12700KF" };
}
public void BuilderDisplay()
{
computer.Display_ = new Display(){ Resolution = "1920*1080" };
}
public void BuilderMouse()
{
computer.Mouse_ = new Mouse(){ BluetoothModel = "罗技(Logitech)无线鼠标M650" };
}
}
4、指导者(可以调整小对象的构造顺序,在某些场景,指导者可以没有)
public class Director
{
public void Construct(Builder builder)
{
builder.BuilderCPU();
builder.BuilderDisplay();
builder.BuilderMouse();
}
}
5、实际调用
//实例化指导者
Director director = new();
//实例化具体构造者
Builder builder = new ConcreteBuilder();
director.Construct(builder);
//返回构造产品 computer
Computer computer = builder.BuilderComputer();
优点
1、分离构建过程和表示:建造者模式允许你分离一个复杂对象的构建过程和它的表示,这使得构
建过程可以独立于实际的对象结构。这样一来,可以更容易地改变一个对象的内部表示。
2、更好的控制对象构建过程:通过指挥者控制对象的构建过程,可以更加灵活地管理对象的创建
流程。指挥者知道如何构建对象,但它并不知道具体的构建细节,从而降低了指挥者与具体构建者
之间的耦合。
缺点
1、不适合构建简单对象:建造者模式适用于构建复杂对象,如果对象比较简单,那么使用建造者
模式可能会显得过于繁琐。
2、增加了类的个数:建造者模式引入了多个新的类(产品类、抽象建造者类、具体建造者类、指
挥者类等),这增加了系统的复杂性。
适用场景
1、需要构建复杂对象:如果一个对象由多个部分组成,并且这些部分之间有复杂的依赖关系或者
构建顺序,那么建造者模式就非常适用。它可以将复杂对象的构建过程分解为多个简单的步骤,每
个步骤由具体的建造者来完成,从而简化构建过程。
2、需要灵活地构建对象:如果需要根据不同的需求来构建对象,且构建过程可能会发生变化,那
么建造者模式可以提供灵活性。通过定义抽象的建造者接口和具体的建造者类,可以很容易地切换
构建逻辑或者添加新的构建者类。
实际运用
在.net5以及更高版本,源码中可以看到,在构建管道以及内置IOC容器时,使用的就是建造者模
式。下面是.NET Core Program.cs的文件。要看具体构造,可以在GitHub上看源码。
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.Build();
return WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseStartup<Startup>()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseConfiguration(configuration);
}
StringBuilder 也是.NET 中的另一个经典的建造者模式的实现。它允许动态地构建字符串,而无需
每次都创建新的字符串对象,这样可以避免引发不必要的内存分配和复制操作。
StringBuilder 通常使用一个内部的字符数组(char[])来存储字符串内容。当字符串被添加到
StringBuilder 中时,StringBuilder 会检查当前的字符数组是否有足够的容量来存储新添加的字符
串。如果容量不够,StringBuilder 就会动态地增加字符数组的大小,以容纳新的字符串。
在最后的ToString方法,返回最终字符串。(StringBuilder 中没有指导者角色。)