c#发展

首页 » 常识 » 问答 » 23种经典软件设计模式建造者模式
TUhjnbcbe - 2025/6/14 17:51:00
意图

建造者模式是一种创建型设计模式,它允许您逐步构建复杂的对象。该模式允许您使用相同的构造代码生成不同类型和表示的对象。

问题

想象一个复杂的对象,它需要耗费大量精力、逐步初始化许多字段和嵌套对象。这样的初始化代码通常被深埋在一个有很多参数的庞大构造函数中。或者更糟糕的是:分散在客户端代码中的各个地方。

具有许多参数的构造函数也有其缺点:并不是所有参数都始终需要。

例如,让我们考虑如何创建一个House(房屋)对象。为了建造一个简单的房子,您需要建造四堵墙和一层地板,安装一扇门,安装一对窗户,并建造一座屋顶。但是,如果您想要一个更大、更明亮的房子,带有后院和其他设施(如供暖系统、管道和电气布线)呢?

最简单的解决方案是扩展基类House并创建一组子类来涵盖所有参数的组合。但是,最终您将得到相当数量的子类。任何新的参数,如门廊风格,都将需要进一步扩展这个层次结构。

还有另一种方法,它不涉及子类的生成。您可以在基类House中创建一个庞大的构造函数,其中包含控制房屋对象的所有可能参数。虽然这种方法确实消除了子类的需求,但也产生了另一个问题。

建造者模式允许您逐步构建复杂的对象。在构建过程中,建造者不允许其他对象访问正在构建的产品。

在大多数情况下,大多数参数都将是未使用的,使构造函数调用非常丑陋。例如,只有一小部分房屋有游泳池,所以与游泳池相关的参数在十次中有九次是无用的。

解决方法

建造者模式建议将对象构建代码从其自身类中提取出来,并将其移动到称为建造者的单独对象中。

建造者模式允许逐步构建复杂对象。在对象构建过程中,建造者模式不允许其他对象访问正在构建的产品。

该模式将对象构造组织成一系列步骤(如构建墙壁、构建门等)。要创建一个对象,您在建造者对象上执行这些步骤的一系列操作。重要的是,您不需要调用所有的步骤,只需要调用那些在特定配置下创建对象所必需的步骤。

在构建各种产品表示形式时,某些构造步骤可能需要不同的实现。例如,小屋的墙可能是用木材建造的,而城堡的墙则必须用石头建造。

在这种情况下,您可以创建几个不同的构造者类,它们以不同的方式实现相同的一组构建步骤。然后,您可以在构建过程中使用这些构造者(即对构建步骤的有序调用)来生产不同类型的对象。

不同的构造者以不同的方式执行相同的任务。

例如,想象一个使用木材和玻璃建造一切的构造者,第二个使用石头和铁建造一切的构造者,以及第三个使用黄金和钻石的构造者。通过调用相同的一系列步骤,您可以从第一个构造者得到一座普通的房屋,从第二个构造者得到一个小城堡,从第三个构造者得到一座宫殿。然而,这只有在调用构建步骤的客户端代码能够使用共同的接口与构造者进行交互时才能实现。

导演

您可以进一步将用于构造产品的构建步骤的一系列调用提取到一个名为导演(Director)的独立类中。导演类定义了执行构建步骤的顺序,而构造者则提供了这些步骤的实现。

在程序中使用导演类并不是严格必需的。您始终可以直接从客户端代码按特定顺序调用构建步骤。然而,导演类可能是一个很好的地方,用于放置各种构建例程,以便您可以在整个程序中重复使用它们。

此外,导演类完全隐藏了产品构造的细节,客户端代码只需要将构建者与导演关联起来,通过导演启动构建过程,并从构建者获取结果。

结构

1、构建者接口声明了所有构建者类型共有的产品构造步骤。

2、具体构建者提供了不同的构建步骤实现。具体构建者可以产生不符合共同接口的产品。

、产品是构建过程中得到的对象。由不同构建者构建的产品不必属于同一类层次结构或接口。

4、导演类定义了调用构建步骤的顺序,使您可以创建和重复使用特定配置的产品。

5、客户端必须将其中一个构建者对象与导演关联起来。通常,这只需要在导演的构造函数中通过参数完成。然后导演在所有后续的构建中使用该构建者对象。然而,还有一种替代方法,即客户端将构建者对象传递给导演的生产方法。在这种情况下,您可以每次与导演一起生产时使用不同的构建者。

伪代码

这个Builder模式的示例说明了在构建不同类型的产品(如汽车)时如何重用相同的对象构造代码,并为它们创建相应的手册。

汽车的逐步构建和相应车型的用户指南的例子。

汽车是一个可以以数百种不同方式构建的复杂对象。我们没有在Car类中堆积一个庞大的构造函数,而是将汽车组装代码提取到一个单独的汽车构建器类中。该类具有一组方法,用于配置汽车的各个部件。

如果客户端代码需要组装一个特殊的、精心调校的汽车型号,它可以直接与构建器进行交互。另一方面,客户端可以将组装任务委托给指挥者类,它知道如何使用构建器来构建几种最受欢迎的汽车型号。

也许你会感到惊讶,但是每辆汽车都需要一本使用手册(说真的,谁会去读它们呢?)。使用手册描述了汽车的每个功能,因此在不同的型号中手册的细节会有所不同。这就是为什么可以重用现有的构建流程来构建真实的汽车和相应的使用手册的原因。当然,构建手册并不同于构建汽车,这就是为什么我们必须提供另一个专门用于编写手册的构建器类。该类实现了与构建汽车的兄弟类相同的构建方法,但是它描述的是汽车的部件。通过将这些构建器传递给同一个指挥者对象,我们可以构建汽车或手册。

最后一步是获取构建的结果对象。金属汽车和纸质使用手册虽然相关,但仍然是非常不同的东西。我们不能在指挥者中放置一个用于获取结果的方法,否则会将指挥者与具体的产品类耦合在一起。因此,我们从执行任务的构建器那里获取构建的结果。

//UsingtheBuilderpatternmakessenseonlywhenyourproducts//arequite

1
查看完整版本: 23种经典软件设计模式建造者模式