【愚公系列】2023年10月 二十三种设计模式(三)-建造者模式(Builder Pattern)
🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
🚀前言
设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。
毫无疑问,设计模式对个人、团队和整个系统都带来了显著的益处。它们将代码开发提升到工程化水平,为软件工程构建提供了坚实的基础,就如同大厦的一块块精巧的砖石一样。在项目中明智地应用设计模式可以完美地解决各种复杂问题。每种设计模式都有相应的原理和最佳实践,它们描述了我们日常开发中不断遇到的问题,以及这些问题的核心解决方法。正是因为这种实用性和通用性,设计模式才能在软件开发中广泛地得以应用。设计模式是构建稳健、可扩展和可维护软件的关键工具,为开发者们提供了解决问题的智慧和指导。
🚀一、建造者模式(Builder Pattern)
建造者模式是一种创建型设计模式,其主要目的是将复杂对象的构建过程与其最终表示分离开来。这意味着通过建造者模式,可以使用相同的构建过程来创建不同的对象表示。
这种模式的核心思想是将构建复杂对象的过程分解成多个简单的步骤,每个步骤由一个具体的建造者对象负责完成。通过将这些步骤按顺序组合起来,最终可以创建出一个完整的复杂对象。
建造者模式的优点在于它提供了一种灵活的方式来构建不同配置的对象,同时将对象的构建与其表示解耦,使得系统更加可维护和可扩展。这种模式常常在需要创建复杂对象,且对象的构建过程涉及多个步骤或配置
🚀二、使用步骤
🔎1.角色
🦋1.1 抽象建造者(Builder)
在建造者模式(Builder Pattern)中,抽象建造者(Builder)是一个关键的概念,它的作用是定义了构建复杂对象的抽象接口和步骤,同时负责规定对象的构建过程。
抽象建造者的主要作用如下:
定义构建步骤:抽象建造者定义了创建复杂对象的构建步骤,通常包括对象的各个部分的构建方法。这些方法可以包括设置对象的属性、组装对象的部件等。
提供构建接口:抽象建造者为客户端提供了一个通用的构建接口,客户端通过这个接口来指导建造者创建对象。这使得客户端可以灵活地指定对象的各个部分以及它们的组合方式。
解耦构建过程:抽象建造者将对象的构建过程与具体的产品类分离开来,使得不同的具体建造者可以创建相同产品的不同表示,同时客户端不需要了解具体建造者的实现细节,从而实现了解耦。
支持多个产品表示:抽象建造者通常不仅仅针对一个具体产品,而是可以支持创建多种不同的产品表示。每个具体的建造者负责创建特定产品的表示。
确保一致性:抽象建造者可以规定一致的构建流程和标准,以确保不同的产品表示都符合一致的构建方式,这对于维护和测试非常有帮助。
抽象建造者在建造者模式中充当了重要的角色,它定义了对象的构建过程和接口,使得客户端能够通过建造者来创建复杂对象,同时实现了对象的构建与表示的分离,提高了系统的可维护性和灵活性。不同的具体建造者可以根据需要创建不同的产品表示
🦋1.2 具体建造者(Concrete Builder)
建造者模式(Builder Pattern)中的具体建造者(Concrete Builder)是实现抽象建造者接口的具体类,它的作用是负责实际构建复杂对象的各个部分,并最终组装成完整的产品。以下是具体建造者的概念和作用:
实现构建步骤:具体建造者实现了抽象建造者中定义的构建步骤,包括设置对象的属性、组装对象的部件等。每个具体建造者都知道如何创建特定产品的各个部分。
负责创建产品:具体建造者的主要责任是根据抽象建造者接口中的定义,逐步构建和组装复杂对象的各个部分,最终创建一个完整的产品。这个产品可以是具体建造者所负责创建的任何类型的对象。
提供访问产品的方法:通常,具体建造者还提供了一个获取构建好的产品的方法,以便客户端可以获取最终的对象表示。这个方法通常在构建过程完成后调用。
可选的配置方法:具体建造者可能会提供一些可选的配置方法,让客户端可以根据需要对对象进行额外的配置或定制。这增加了建造者模式的灵活性。
与指挥者协作:具体建造者通常与指挥者(Director)协作,指挥者负责按照一定的顺序来调用具体建造者的方法,从而完成对象的构建过程。指挥者负责组织建造者的工作流程。
支持多个具体产品:建造者模式的一个重要特点是,可以有多个不同的具体建造者,每个具体建造者负责创建不同类型的产品。这样可以实现在相同的构建过程下创建不同的对象表示。
具体建造者是建造者模式中的关键组件,它根据抽象建造者接口的定义来实际构建和组装复杂对象的各个部分,从而创建出最终的产品。不同的具体建造者可以用于创建不同类型的对象,提高了系统的可扩展性和灵活性。同时,具体建造者与指挥者协同工作,确保构建过程按照一定的顺序进行。
🦋1.3 指导者(Director)
建造者模式(Builder Pattern)中的指导者(Director)是一个协调者,它的作用是负责按照一定的顺序来调用具体建造者(Concrete Builder)的方法,从而协调构建复杂对象的过程,最终创建一个完整的产品。以下是指导者的概念和作用:
定义构建顺序:指导者知道在构建复杂对象时应该按照什么顺序调用具体建造者的方法。它可以根据特定的构建流程来指导建造者的工作,确保对象的各个部分按正确的顺序被创建和组装。
隐藏构建细节:指导者将构建对象的过程封装在自己的方法中,对客户端隐藏了具体建造者的细节。客户端只需要与指导者交互,而不需要了解对象的构建过程和细节。
提供高层接口:指导者通常提供一个高层次的接口,通过这个接口客户端可以简单地创建复杂对象。客户端只需提供必要的参数和配置信息,指导者负责处理对象的构建。
支持不同配置:指导者可以根据客户端提供的不同配置信息来协调不同的具体建造者,从而创建不同配置的对象。这增加了灵活性,使客户端能够轻松地创建多种对象表示。
构建复杂对象:最终,指导者的主要任务是确保复杂对象的正确构建。它通过协调具体建造者的工作,确保各个部分按照正确的顺序创建和组装,以创建一个完整的产品对象。
指导者在建造者模式中充当了协调者的角色,它定义了构建复杂对象的顺序和流程,封装了构建细节,提供了高层次的接口供客户端使用。通过指导者,客户端可以轻松地创建复杂对象,同时保持了对象构建过程的灵活性和可维护性。指导者与具体建造者协同工作,确保复杂对象的正确构建。
🦋1.4 产品类(Product)
在建造者模式(Builder Pattern)中,产品类(Product)代表要构建的复杂对象,它的作用是承载和存储具体建造者(Concrete Builder)所创建的各个部分,并最终组装成完整的对象。以下是产品类的概念和作用:
存储对象部分:产品类用于存储复杂对象的各个部分或属性。具体建造者在构建对象时会逐步填充产品类的属性或部件,最终形成一个完整的对象。
提供访问接口:产品类通常提供了访问对象部分的方法,使得客户端可以获取构建好的对象的各个部分或属性。这些方法通常用于获取对象的状态信息。
不可变性(可选):在某些情况下,产品类可以设计成不可变的,即一旦创建后,就不能再修改对象的状态。这有助于确保对象的一致性和安全性。
表达不同产品表示:如果建造者模式支持创建多个不同类型的产品,那么产品类可以根据具体建造者的不同实现来表达不同产品表示。每个产品类的结构和属性可以根据具体产品的需要而变化。
封装对象构建细节:产品类的存在有助于封装对象构建的细节,客户端不需要关心如何构建对象,而是通过产品类获取已构建好的对象。
支持多种产品:一个产品类可以用于表示多个不同类型的产品,具体建造者负责填充产品类的属性以适应不同产品的需求。
产品类在建造者模式中扮演着重要的角色,它是复杂对象的容器,用于存储和表达各个部分或属性。产品类的设计要根据具体的需求和复杂对象的特性来确定,它负责承载构建过程中的信息,并在最终构建完成后提供给客户端。这有助于实现对象的构建与表示的分离,提高了系统的可维护性和灵活性。
🔎2.示例
命名空间BuilderPattern中包含Vehicle机动车类充当产品类,Builder基类为抽象建造者,东风悦达Yuedakia类、大众汽车Volkswagen类、特斯拉Tesla类。另外包含1个机动车扩展类和1个指导者。本示例向大家演示3个不同的汽车厂商在生产比较复杂的汽车时所采用的策略。
public abstract class Builder {
protected Vehicle _product = new Vehicle();
public abstract void BuildCarframe();
public abstract void BuildWheel();
public abstract void BuildDoor();
public abstract void BuildApparatus();
public abstract void BuildColor();
public virtual Vehicle GetResult() {
return _product;
}
}
建造者基类Builder,定义生产不同汽车部位的接口并在内部维持对机动车的引用。
public class Tesla : Builder {
public override void BuildCarframe() {
_product.Carframe = "ZZ32093M3485C1356";
}
public override void BuildWheel() {
_product.Wheel = 4;
}
public override void BuildDoor() {
_product.Door = 5;
}
public override void BuildApparatus() {
_product.Apparatus = "Model X";
}
public override void BuildColor() {
_product.Color = Color.Red;
}
}
具体建造者特斯拉Tesla类,实现抽象建造者Builder的接口。
public class Volkswagen : Builder {
public override void BuildCarframe() {
_product.Carframe = "VS89362P1903C9852";
}
public override void BuildWheel() {
_product.Wheel = 4;
}
public override void BuildDoor() {
_product.Door = 4;
}
public override void BuildApparatus() {
_product.Apparatus = "Skoda";
}
public override void BuildColor() {
_product.Color = Color.Blue;
}
}
具体建造者大众汽车Volkswagen类,实现抽象建造者Builder的接口。
public class Yuedakia : Builder {
public override void BuildCarframe() {
_product.Carframe = "YK9391J0231L30D32";
}
public override void BuildWheel() {
_product.Wheel = 4;
}
public override void BuildDoor() {
_product.Door = 4;
}
public override void BuildApparatus() {
_product.Apparatus = "Kia K3";
}
public override void BuildColor() {
_product.Color = Color.Wheat;
}
}
具体建造者东风悦达Yuedakia类,实现抽象建造者Builder的接口。
public class Vehicle {
public string Carframe { get; set; }
public int Wheel { get; set; }
public int Door { get; set; }
public string Apparatus { get; set; }
public Color Color { get; set; }
public void Print() {
Console.WriteLine($"{this.VehicleInfo()}");
}
}
机动车Vehicle类,这是我们通过建造者模式所要创建的复杂对象。
public class Director {
public void Construct(Builder builder) {
builder.BuildCarframe();
builder.BuildWheel();
builder.BuildDoor();
builder.BuildApparatus();
builder.BuildColor();
}
}
这是指导类Director,它负责对象的创建过程。
public static class Extentions {
public static string VehicleInfo(this Vehicle vehicle) {
var type = vehicle.GetType();
var properties = type.GetProperties();
var result = string.Empty;
foreach (var prop in properties) {
result +=
$"{prop.Name}:{prop.GetValue(vehicle, null)}{Environment.NewLine}";
}
return result;
}
}
一个扩展类,方便演示过程中打印出相关信息。
public class Program {
private static Director _director = null;
private static List<Builder> _builders = null;
private static Vehicle _vehicle = null;
public static void Main(string[] args) {
_director = new Director();
_vehicle = new Vehicle();
_builders = new List<Builder>() {
new Tesla(),
new Volkswagen(),
new Yuedakia()
};
foreach (var builder in _builders) {
_director.Construct(builder);
_vehicle = builder.GetResult();
_vehicle.Print();
}
Console.ReadKey();
}
}
以上是调用方的代码,分别维持对指导者、建造者和机动车的引用,接下来我们创建了3辆汽车,特斯拉的Model X、大众汽车的Skoda和东风悦达的Kia K3。以下是这个案例的输出结果:
Carframe:ZZ32093M3485C1356
Wheel:4
Door:5
Apparatus:Model X
Color:Color [Red]
Carframe:VS89362P1903C9852
Wheel:4
Door:4
Apparatus:Skoda
Color:Color [Blue]
Carframe:YK9391J0231L30D32
Wheel:4
Door:4
Apparatus:Kia K3
Color:Color [Wheat]
🚀总结
🔎1.优点
建造者模式(Builder Pattern)是一种常用的设计模式,它具有许多优点,包括:
分离构建和表示:建造者模式将一个复杂对象的构建过程与其最终表示分离开来。这使得客户端代码不必关心对象的具体构建细节,只需通过指导者或具体建造者来创建对象,从而降低了客户端与具体构建过程的耦合度。
灵活性:建造者模式允许客户端根据需要选择不同的具体建造者来构建对象。这使得客户端可以根据需求创建不同的对象表示,而无需修改现有代码。
可读性:通过使用建造者模式,可以清晰地看到对象的构建过程,因为它将构建步骤逐一列出。这有助于提高代码的可读性和可维护性。
控制复杂对象的创建过程:建造者模式允许开发者控制对象的创建过程。具体建造者可以根据需要执行一系列复杂的构建步骤,如验证、初始化等,以确保对象的正确构建。
支持不同配置:由于可以有多个具体建造者,每个具体建造者可以根据不同的配置信息来构建对象。这使得可以轻松地创建多种不同配置的对象。
符合单一职责原则:建造者模式将对象的构建过程分解成多个步骤,每个步骤由一个具体建造者负责。这有助于遵循单一职责原则,每个建造者只负责一个方面的构建工作。
可扩展性:如果需要新增一种产品类型,只需创建新的具体建造者和相应的产品类,而无需修改现有代码。这提高了系统的可扩展性。
建造者模式在构建复杂对象时提供了一种优雅的解决方案,它将构建过程模块化,降低了代码的复杂性,提高了代码的可维护性和可扩展性,同时使客户端更容易使用和理解对象的构建过程。这些优点使建造者模式在软件开发中广泛应用。
🔎2.缺点
尽管建造者模式(Builder Pattern)具有许多优点,但也存在一些缺点,需要在使用时考虑:
增加代码量:引入建造者模式会增加代码的复杂性和量。因为需要创建具体建造者、指导者和产品类,可能会导致代码中出现大量的额外类和接口,使代码变得更加庞大。
不适合简单对象:如果要构建的对象非常简单,没有复杂的构建过程或部件,使用建造者模式可能会显得繁琐,不是最佳选择。
可能导致多余的对象创建:在建造者模式中,即使客户端不需要所有的构建步骤,也会创建完整的产品对象。这可能会导致内存资源的浪费,特别是在构建复杂对象时。
不够灵活:虽然建造者模式提供了一定的灵活性,但在某些情况下可能无法满足特定需求。如果需要动态地根据条件来构建对象,建造者模式可能会显得不够灵活。
可能引入冗余代码:在具体建造者中,可能会出现一些重复的构建逻辑,这可能会导致代码冗余,尤其是在有多个具体建造者时。
学习成本:对于不熟悉建造者模式的开发人员来说,学习和理解模式的概念和实现细节可能需要一定的时间和努力。
增加复杂性:在简单的情况下,引入建造者模式可能会增加代码的复杂性,使代码难以理解和维护。
建造者模式适用于构建复杂对象的情况,但在简单情况下可能会显得过于繁琐。在选择是否使用建造者模式时,需要权衡其优点和缺点,并根据具体需求和项目的复杂性来做出决策。
🔎3.使用场景
建造者模式(Builder Pattern)适用于以下情景:
创建复杂对象:当需要创建一个复杂对象,该对象具有多个部分或属性,且这些部分之间存在复杂的关联关系时,建造者模式是一个很好的选择。它可以将对象的构建过程分解成多个步骤,每个步骤由具体建造者负责,最终组装成一个完整的对象。
多种配置:如果需要创建多种不同配置的对象,而这些配置可以共享相同的构建步骤,建造者模式非常有用。不同的具体建造者可以根据配置信息来构建不同的对象。
隐藏构建细节:当需要隐藏对象的构建细节,使客户端只需关注高层次的构建过程时,建造者模式可以提供抽象接口,将构建过程封装在具体建造者中。
防止不一致状态:建造者模式可以确保在构建对象的过程中不会出现不一致的状态。只有在对象构建完成后,才将其提供给客户端使用,从而避免了部分构建和未完成构建状态的问题。
支持可扩展性:如果需要新增不同类型的产品或部件,可以通过创建新的具体建造者来扩展建造者模式,而无需修改现有代码。
逐步构建对象:建造者模式允许逐步构建对象,每一步都可以添加一些额外的处理逻辑,例如验证、初始化等。
提高可维护性:通过将对象构建过程模块化,建造者模式可以提高代码的可维护性。每个具体建造者只负责自己的一部分工作,使得修改或扩展对象的构建变得更加容易。
建造者模式适用于构建复杂对象,需要灵活支持不同配置或需要隐藏构建细节的情况。它有助于降低代码的耦合度,提高可读性和可维护性,特别适用于大型项目或需要创建多种不同类型对象的应用中。
🚀感谢:给读者的一封信
亲爱的读者,
我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。
如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。
我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。
如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。
再次感谢您的阅读和支持!
最诚挚的问候, “愚公搬代码”
- 点赞
- 收藏
- 关注作者
评论(0)