C# 设计模式:第三章 创建者模式 之 建造者模式(Builder Pattern)
欢迎来到 C# 设计模式 的第三章!在这一章中,我们将深入探讨 建造者模式(Builder Pattern)。建造者模式是一种创建型设计模式,它允许你分步骤地构建复杂对象,而不需要一次性完成所有操作。想象一下,如果你在建造一座房子,你会先打地基,再建墙壁,最后安装屋顶,而不是一口气把整个房子都盖好。建造者模式正是这样一种模式,它让你可以逐步构建复杂的对象,而不会让代码变得混乱不堪。
第一节:什么是建造者模式?
1. 概念:
建造者模式的核心思想是:将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。换句话说,建造者模式允许你通过多个步骤来构建一个对象,而不是一次性完成所有操作。每个步骤都可以独立进行,最终组合成一个完整的对象。
幽默小贴士:
建造者模式就像是编程世界里的“乐高大师”,你可以一块一块地搭建出复杂的结构,而不需要一次把所有的积木都拼在一起。这样不仅更灵活,还能让你随时调整设计! 🧱
2. 为什么需要建造者模式?
- 简化复杂对象的创建:有时候,创建一个对象的过程非常复杂,涉及到多个参数和步骤。通过建造者模式,你可以将这些复杂的创建过程分解为多个简单的步骤,使代码更加清晰和易于维护。
- 避免构造函数的参数爆炸:如果一个类的构造函数需要传递大量的参数,代码会变得非常难以阅读和维护。建造者模式可以通过逐步设置属性来避免这种情况,使代码更加简洁。
- 支持多态性:建造者模式允许你在构建过程中动态地选择不同的实现类,从而支持多态性。你可以根据需要创建不同类型的对象,而不需要修改现有的代码。
第二节:真实案例
1. 汽车制造系统:
想象一下,你在开发一个汽车制造系统,用户可以选择不同的配置来定制他们的汽车。例如,用户可以选择发动机类型、轮胎品牌、内饰颜色等。为了实现这个功能,你可以使用建造者模式来逐步构建汽车对象,而不是一次性传递所有的参数。
幽默小贴士:
在汽车制造系统中,建造者模式就像是“汽车组装线”,你可以一步一步地添加不同的零件,最终组装出一辆完整的汽车。就像《疯狂原始人》中的洞穴人一样,他们也是从最基础的工具开始,逐渐发明了轮子、马车,最后造出了汽车! 🚗
2. 披萨订单系统:
假设你在开发一个披萨订单系统,用户可以选择不同的配料、面饼类型、酱料等。为了实现这个功能,你可以使用建造者模式来逐步构建披萨对象,而不是一次性传递所有的参数。这样可以让用户更加灵活地定制他们的披萨,同时也能让代码更加简洁和易读。
幽默小贴士:
在披萨订单系统中,建造者模式就像是“披萨制作大师”,你可以一步一步地添加不同的配料,最终制作出一份完美的披萨。就像《料理鼠王》中的小老鼠雷米一样,它也是通过一步步的努力,最终成为了一名顶级厨师! 🍕
第三节:实施方法
在 C# 中实现建造者模式通常涉及以下几个类:
Product类:这是你要构建的复杂对象。它可以包含多个属性和方法,用于表示最终的产品。Builder接口:这是一个定义了构建步骤的接口,所有的具体建造者类都必须实现这个接口。ConcreteBuilder类:这是实现了Builder接口的具体类。它负责逐步构建Product对象,并提供一个GetResult()方法来返回最终的产品。Director类:这是一个协调者类,它负责调用具体的建造者类来构建产品。Director类并不关心具体的构建细节,它只负责按照一定的顺序调用建造者的各个步骤。
第四节:类之间的关系
1. 所需的类
在实现建造者模式时,通常需要以下几个类:
-
Product类:- 这是你最终要构建的复杂对象。它可以包含多个属性和方法,用于表示最终的产品。
-
IBuilder接口:- 这是一个定义了构建步骤的接口,所有的具体建造者类都必须实现这个接口。它通常包含一些抽象的方法,用于逐步构建
Product对象。
- 这是一个定义了构建步骤的接口,所有的具体建造者类都必须实现这个接口。它通常包含一些抽象的方法,用于逐步构建
-
ConcreteBuilder类:- 这是实现了
IBuilder接口的具体类。它负责逐步构建Product对象,并提供一个GetResult()方法来返回最终的产品。
- 这是实现了
-
Director类:- 这是一个协调者类,它负责调用具体的建造者类来构建产品。
Director类并不关心具体的构建细节,它只负责按照一定的顺序调用建造者的各个步骤。
- 这是一个协调者类,它负责调用具体的建造者类来构建产品。
-
Client类(客户端代码):- 这是使用建造者模式的客户端代码。它通过
Director类来协调具体的建造者类,最终获取构建好的Product对象。
- 这是使用建造者模式的客户端代码。它通过
-
Pizza类(可选):- 如果你需要构建一个具体的对象(如披萨),你可以为这个对象定义一个单独的类。这样可以确保在构建过程中,对象的属性可以被逐步设置。
2. 类的详细说明
1. Product 类
// 定义产品类
public class Product
{
private List<string> parts = new List<string>();
// 添加部件
public void AddPart(string part)
{
parts.Add(part);
}
// 显示产品信息
public void Show()
{
Console.WriteLine("产品组成部分:");
foreach (var part in parts)
{
Console.WriteLine($"- {part}");
}
}
}
- 作用:
Product类是你最终要构建的复杂对象。它可以包含多个属性和方法,用于表示最终的产品。在这个例子中,Product类包含了一个parts列表,用于存储产品的各个组成部分。 - 优点:通过逐步添加部件,
Product类可以灵活地构建出不同的产品,而不需要一次性完成所有操作。
2. IBuilder 接口
// 定义建造者接口
public interface IBuilder
{
void BuildPartA();
void BuildPartB();
Product GetResult();
}
- 作用:
IBuilder接口定义了构建步骤的抽象方法。所有的具体建造者类都必须实现这个接口,并提供具体的构建逻辑。 - 优点:通过接口定义构建步骤,可以支持多态性,允许客户端代码动态地选择不同的建造者类。
3. ConcreteBuilder 类
// 实现具体建造者类
public class ConcreteBuilder : IBuilder
{
private Product product = new Product();
// 构建部件 A
public void BuildPartA()
{
product.AddPart("部件 A");
}
// 构建部件 B
public void BuildPartB()
{
product.AddPart("部件 B");
}
// 返回构建好的产品
public Product GetResult()
{
return product;
}
}
- 作用:
ConcreteBuilder类实现了IBuilder接口,并提供了具体的构建逻辑。它负责逐步构建Product对象,并提供一个GetResult()方法来返回最终的产品。 - 优点:通过实现具体的构建逻辑,
ConcreteBuilder类可以灵活地构建出不同的产品,而不需要修改现有的代码。
4. Director 类
// 定义导演类
public class Director
{
private IBuilder builder;
// 设置建造者
public void SetBuilder(IBuilder builder)
{
this.builder = builder;
}
// 构建产品
public void Construct()
{
builder.BuildPartA();
builder.BuildPartB();
}
}
- 作用:
Director类是一个协调者类,它负责调用具体的建造者类来构建产品。Director类并不关心具体的构建细节,它只负责按照一定的顺序调用建造者的各个步骤。 - 优点:通过
Director类,客户端代码可以轻松地构建不同的产品,而不需要直接调用建造者的各个方法。
5. Client 类(客户端代码)
class Program
{
static void Main(string[] args)
{
// 创建导演
Director director = new Director();
// 创建具体建造者
IBuilder builder = new ConcreteBuilder();
// 设置建造者
director.SetBuilder(builder);
// 构建产品
director.Construct();
// 获取构建好的产品
Product product = builder.GetResult();
// 显示产品信息
product.Show();
}
}
- 作用:
Client类是使用建造者模式的客户端代码。它通过Director类来协调具体的建造者类,最终获取构建好的Product对象。 - 优点:通过使用
Director类,客户端代码可以轻松地构建不同的产品,而不需要直接调用建造者的各个方法。
6. Pizza 类(可选)
// 定义披萨类
public class Pizza
{
public string Dough { get; set; }
public string Sauce { get; set; }
public List<string> Toppings { get; set; } = new List<string>();
public void Show()
{
Console.WriteLine("披萨详情:");
Console.WriteLine($"- 面饼: {Dough}");
Console.WriteLine($"- 酱料: {Sauce}");
Console.WriteLine("配料:");
foreach (var topping in Toppings)
{
Console.WriteLine($"- {topping}");
}
}
}
- 作用:
Pizza类是一个具体的对象类,用于表示披萨。它包含了一些属性,如Dough(面饼)、Sauce(酱料)和Toppings(配料)。你可以通过建造者模式逐步设置这些属性,最终构建出一份完整的披萨。 - 优点:通过逐步设置属性,
Pizza类可以灵活地构建出不同的披萨,而不需要一次性传递所有的参数。
3. 类之间的关系
现在我们已经了解了所有需要的类,接下来让我们通过类图来展示这些类之间的关系。
类图示例:
+-------------------+
| IBuilder |
+-------------------+
| + BuildPartA() |
| + BuildPartB() |
| + GetResult(): Product |
+-------------------+
^
|
+-------------------+
| ConcreteBuilder |
+-------------------+
| - product: Product|
| + BuildPartA() |
| + BuildPartB() |
| + GetResult(): Product |
+-------------------+
^
|
+-------------------+
| Director |
+-------------------+
| - builder: IBuilder |
| + SetBuilder(IBuilder) |
| + Construct() |
+-------------------+
^
|
+-------------------+
| Client |
+-------------------+
| + Main(): void |
+-------------------+
+-------------------+
| Product |
+-------------------+
| - parts: List<string> |
| + AddPart(string) |
| + Show() |
+-------------------+
+-------------------+
| Pizza |
+-------------------+
| - Dough: string |
| - Sauce: string |
| - Toppings: List<string> |
| + Show() |
+-------------------+
幽默小贴士:
类图就像是编程世界的“建筑图纸”,它展示了各个类之间的关系。
IBuilder接口是“建筑师”,它定义了如何建造房屋的规则。ConcreteBuilder类是“施工队”,它负责按照规则逐步建造房屋。Director类是“项目经理”,它负责协调施工队的工作,确保房屋按照计划建造。Client类则是“房主”,它只需要告诉项目经理想要什么样的房屋,而不需要亲自参与施工。 🏠
第五节:程序执行与输出
让我们通过几个实际的代码示例来演示建造者模式的使用。
示例 1:基本建造者模式
using System;
class Program
{
static void Main(string[] args)
{
// 创建导演
Director director = new Director();
// 创建具体建造者
IBuilder builder = new ConcreteBuilder();
// 设置建造者
director.SetBuilder(builder);
// 构建产品
director.Construct();
// 获取构建好的产品
Product product = builder.GetResult();
// 显示产品信息
product.Show();
}
}
输出结果:
产品组成部分:
- 部件 A
- 部件 B
代码分析:
- 我们首先创建了一个
Director对象,它是负责协调建造过程的类。 - 然后,我们创建了一个
ConcreteBuilder对象,它是具体的建造者类,负责逐步构建Product对象。 - 接下来,我们通过
SetBuilder()方法将ConcreteBuilder设置为Director的建造者。 - 最后,我们调用
Construct()方法来构建产品,并通过GetResult()方法获取构建好的Product对象。 - 最终,我们调用
Show()方法来显示产品的组成部分。
幽默小贴士:
基本建造者模式就像是“搭积木”,你可以一步一步地添加不同的积木块,最终搭出一个完整的结构。就像《乐高电影》中的艾米特一样,他也是通过一步步的努力,最终搭建出了一个充满创意的世界! 🧱
示例 2:披萨建造者模式
using System;
// 定义披萨建造者接口
public interface IPizzaBuilder
{
void BuildDough();
void BuildSauce();
void BuildToppings();
Pizza GetPizza();
}
// 实现具体披萨建造者类
public class HawaiianPizzaBuilder : IPizzaBuilder
{
private Pizza pizza = new Pizza();
public void BuildDough()
{
pizza.Dough = "厚底";
}
public void BuildSauce()
{
pizza.Sauce = "番茄酱";
}
public void BuildToppings()
{
pizza.Toppings.Add("火腿");
pizza.Toppings.Add("菠萝");
}
public Pizza GetPizza()
{
return pizza;
}
}
// 定义导演类
public class PizzaDirector
{
private IPizzaBuilder builder;
public void SetBuilder(IPizzaBuilder builder)
{
this.builder = builder;
}
public void Construct()
{
builder.BuildDough();
builder.BuildSauce();
builder.BuildToppings();
}
}
class Program
{
static void Main(string[] args)
{
// 创建导演
PizzaDirector director = new PizzaDirector();
// 创建具体建造者
IPizzaBuilder builder = new HawaiianPizzaBuilder();
// 设置建造者
director.SetBuilder(builder);
// 构建披萨
director.Construct();
// 获取构建好的披萨
Pizza pizza = builder.GetPizza();
// 显示披萨信息
pizza.Show();
}
}
输出结果:
披萨详情:
- 面饼: 厚底
- 酱料: 番茄酱
配料:
- 火腿
- 菠萝
代码分析:
- 我们定义了一个
IPizzaBuilder接口,它定义了构建披萨的步骤,包括BuildDough()(构建面饼)、BuildSauce()(构建酱料)和BuildToppings()(构建配料)。 - 然后,我们实现了一个
HawaiianPizzaBuilder类,它是具体的建造者类,负责逐步构建夏威夷披萨。 - 接下来,我们创建了一个
PizzaDirector类,它是负责协调建造过程的类。PizzaDirector类并不关心具体的构建细节,它只负责按照一定的顺序调用建造者的各个步骤。 - 最后,我们通过
Construct()方法来构建披萨,并通过GetPizza()方法获取构建好的Pizza对象。 - 最终,我们调用
Show()方法来显示披萨的详细信息。
幽默小贴士:
披萨建造者模式就像是“披萨制作大师”,你可以一步一步地添加不同的配料,最终制作出一份完美的披萨。就像《料理鼠王》中的小老鼠雷米一样,它也是通过一步步的努力,最终成为了一名顶级厨师! 🍕
第六节:注意事项
虽然建造者模式非常有用,但在使用时也有一些需要注意的地方:
-
避免过度使用:
- 建造者模式适用于那些创建过程比较复杂,或者需要频繁创建相似对象的场景。如果你的对象创建过程比较简单,或者不需要分步骤构建,那么建造者模式可能并不是最佳选择。
-
保持建造者类的独立性:
- 建造者类应该尽量保持独立,避免与其他类产生过多的依赖关系。这样可以确保建造者类的灵活性和可复用性。
-
支持多态性:
- 建造者模式允许你在构建过程中动态地选择不同的实现类,从而支持多态性。你可以根据需要创建不同类型的对象,而不需要修改现有的代码。
-
避免重复代码:
- 在实现建造者模式时,尽量避免在多个建造者类中重复相同的代码。可以通过提取公共逻辑或将重复的代码封装在基类中来减少冗余。
幽默小贴士:
建造者模式虽然强大,但也需要谨慎使用。毕竟,即使是“乐高大师”也需要懂得适可而止,不能随便搭出一切! 🧱
第七节:本章总结
在这章中,我们学习了 建造者模式 的基本概念、应用场景、实现方法以及注意事项。建造者模式允许你分步骤地构建复杂对象,而不需要一次性完成所有操作。它在简化复杂对象的创建、避免构造函数的参数爆炸和支持多态性方面有着重要的作用。
我们通过两个实际的代码示例展示了如何在 C# 中实现建造者模式,包括基本建造者模式和披萨建造者模式。最后,我们还讨论了一些使用建造者模式时需要注意的地方,帮助你在实际开发中做出明智的选择。
幽默小贴士:
建造者模式就像是编程世界里的“乐高大师”,你可以一块一块地搭建出复杂的结构,而不需要一次把所有的积木都拼在一起。这样不仅更灵活,还能让你随时调整设计! 🧱
结束语
亲爱的学员们,恭喜你完成了 C# 设计模式 的第三章!通过学习建造者模式,你已经掌握了如何分步骤地构建复杂对象,避免了代码的混乱和冗长。接下来,我们将继续探索更多的设计模式,帮助你编写更加优雅、灵活和可维护的代码。
更多推荐


所有评论(0)