设计模式 建造者模式 Builder java
作者:互联网
生成器设计模式是一种创建性设计模式,允许使用 Builder 对象逐步创建复杂对象。客户端代码不是直接创建对象,而是在 Builder 对象上调用一系列方法来创建对象。这允许在创建对象时具有更大的灵活性,因为相同的客户端代码可用于创建具有不同实现的对象。
生成器设计模式的关键元素是生成器界面、混凝土生成器、控制器和产品。
生成器接口定义用于创建对象各部分的方法。这些方法通常由控制器调用。
ConcreteBuilder 是一个实现 Builder 接口并提供用于创建对象各部分的实际实现的类。
控制器负责使用生成器对象来创建对象。它通过在生成器对象上调用适当的方法来执行此操作。
产品是由构建器创建的复杂对象。它由构建器创建的零件组成。
下面是如何使用生成器设计模式的示例:
想象一下,您正在创建一个用于建造房屋的工具。可以建造多种类型的房屋,例如单层房屋,两层房屋和带地下室的房屋。每种类型的房屋都有一组不同的建造步骤。
要使用 Builder 设计模式建造房屋,您需要创建一个 Builder 界面,该界面定义了构建房屋各个部分(例如地基、墙壁、屋顶等)的方法。然后,您将为每种类型的房屋创建 ConcreteBuilder 类,这些类实现 Builder 接口并提供用于构建该类型房屋的特定实现。
然后,客户端代码将创建一个特定的 ConcreteBuilder 对象并将其传递给控制器。然后,控制器将在 Builder 对象上调用适当的方法来构建房屋。这允许使用相同的客户端代码来构建不同类型的房屋,因为具体的实现由 ConcreteBuilder 提供。
对于代码,让我们看看:
using System; namespace BuilderDesignPattern { // Builder interface public interface IHouseBuilder { void BuildFoundation(); void BuildWalls(); void BuildRoof(); House GetHouse(); } // Concrete Builder public class SingleStoryHouseBuilder : IHouseBuilder { private House _house = new House(); public void BuildFoundation() { Console.WriteLine("Building foundation for single-story house"); _house.Add("Foundation"); } public void BuildWalls() { Console.WriteLine("Building walls for single-story house"); _house.Add("Walls"); } public void BuildRoof() { Console.WriteLine("Building roof for single-story house"); _house.Add("Roof"); } public House GetHouse() { return _house; } } // Concrete Builder public class TwoStoryHouseBuilder : IHouseBuilder { private House _house = new House(); public void BuildFoundation() { Console.WriteLine("Building foundation for two-story house"); _house.Add("Foundation"); } public void BuildWalls() { Console.WriteLine("Building walls for two-story house"); _house.Add("Walls"); } public void BuildRoof() { Console.WriteLine("Building roof for two-story house"); _house.Add("Roof"); } public House GetHouse() { return _house; } } // Product public class House { private string[] _parts; public House() { _parts = new string[3]; } public void Add(string part) { for (int i = 0; i < _parts.Length; i++) { if (_parts[i] == null) { _parts[i] = part; break; } } } public void Show() { Console.WriteLine("\nHouse is complete. It includes the following parts:"); foreach (string part in _parts) { Console.WriteLine(part); } } } // Director public class HouseBuilder { public void Construct(IHouseBuilder houseBuilder) { houseBuilder.BuildFoundation(); houseBuilder.BuildWalls(); houseBuilder.BuildRoof(); } } }
您可以使用客户大小的构建器来创建这样的房屋:
class Program { static void Main(string[] args) { HouseBuilder builder = new HouseBuilder(); IHouseBuilder singleStoryHouseBuilder = new SingleStoryHouseBuilder(); IHouseBuilder twoStoryHouseBuilder = new TwoStoryHouseBuilder(); // Build single-story house builder.Construct(singleStoryHouseBuilder); House singleStoryHouse = singleStoryHouseBuilder.GetHouse(); singleStoryHouse.Show(); // Build two-story house builder.Construct(twoStoryHouseBuilder); House twoStoryHouse = twoStoryHouseBuilder.GetHouse(); twoStoryHouse.Show(); } }
假设您正在开发一个用于创建网页的软件应用程序。网页可以具有不同的布局,例如单列布局、两列布局和三列布局。每个网页还具有一组可以包含的元素,例如页眉、导航菜单和页脚。
要使用 Builder 设计模式创建网页,您可以创建一个界面来定义构建网页各种元素的方法(例如 setHeader()、setNavigationMenu()、setFooter() 等)。然后,您可以为每种类型的布局创建具体的类,例如 、 和 ,这些类实现接口并提供用于创建该类型布局的特定实现。WebPageBuilder
OneColumnLayoutBuilder
TwoColumnLayoutBuilder
ThreeColumnLayoutBuilder
WebPageBuilder
然后,客户端代码将创建一个特定对象并将其传递给 ,然后 将在对象上调用适当的方法来创建网页。这允许使用相同的客户端代码来创建不同类型的网页,因为具体的实现由具体类提供。WebPageBuilder
WebPageDirector
WebPageBuilder
WebPageBuilder
要创建它,您必须按照以下步骤操作:
首先,你确实需要一个产品。这是表示正在构建的产品的类。它具有用于存储产品不同部分的各种字段。这是其中之一:
// Product public class WebPage { public string Header { get; set; } public string Menu { get; set; } public string Footer { get; set; } public void Show() { Console.WriteLine("\nWeb page is complete. It includes the following elements:"); Console.WriteLine("Header: " + Header); Console.WriteLine("Menu: " + Menu); Console.WriteLine("Footer: " + Footer); } }
其次,您必须创建 Builder 接口,该接口是定义构建产品各个部分的方法的接口。它由混凝土生成器类实现。
// Builder interface public interface IWebPageBuilder { void SetHeader(string header); void SetNavigationMenu(string menu); void SetFooter(string footer); WebPage GetWebPage(); }
第三部分是混凝土建造者。这些类实现生成器接口并提供用于生成产品的特定实现。可以有多个混凝土生成器类,每个类创建产品的不同版本。
// Concrete Builder public class OneColumnLayoutBuilder : IWebPageBuilder { private WebPage _webPage = new WebPage(); public void SetHeader(string header) { _webPage.Header = header; } public void SetNavigationMenu(string menu) { _webPage.Menu = menu; } public void SetFooter(string footer) { _webPage.Footer = footer; } public WebPage GetWebPage() { return _webPage; } } // Concrete Builder public class TwoColumnLayoutBuilder : IWebPageBuilder { private WebPage _webPage = new WebPage(); public void SetHeader(string header) { _webPage.Header = header; } public void SetNavigationMenu(string menu) { _webPage.Menu = menu; } public void SetFooter(string footer) { _webPage.Footer = footer; } public WebPage GetWebPage() { return _webPage; } } // Concrete Builder public class ThreeColumnLayoutBuilder : IWebPageBuilder { private WebPage _webPage = new WebPage(); public void SetHeader(string header) { _webPage.Header = header; } public void SetNavigationMenu(string menu) { _webPage.Menu = menu; } public void SetFooter(string footer) { _webPage.Footer = footer; } public WebPage GetWebPage() { return _webPage; } }
最后,您需要一个控制器来定义构建步骤。Director 是一个使用生成器接口构造产品的类。它负责创建构建产品的正确步骤序列。
// Director public class WebPageDirector { public void Construct(IWebPageBuilder builder) { builder.SetHeader("Header"); builder.SetNavigationMenu("Menu"); builder.SetFooter("Footer"); } }
好的,就是这样。它已准备好在客户端上使用或您想要使用的位置使用。让我们创建一个网页,嗯?
class Program { static void Main(string[] args) { // Create director and builders WebPageDirector director = new WebPageDirector(); IWebPageBuilder oneColumnBuilder = new OneColumnLayoutBuilder(); IWebPageBuilder twoColumnBuilder = new TwoColumnLayoutBuilder(); IWebPageBuilder threeColumnBuilder = new ThreeColumnLayoutBuilder(); // Construct one-column web page Console.WriteLine("Building one-column web page"); director.Construct(oneColumnBuilder); WebPage oneColumnWebPage = oneColumnBuilder.GetWebPage(); oneColumnWebPage.Show(); // Construct two-column web page Console.WriteLine("\nBuilding two-column web page"); director.Construct(twoColumnBuilder); WebPage twoColumnWebPage = twoColumnBuilder.GetWebPage(); twoColumnWebPage.Show(); // Construct three-column web page Console.WriteLine("\nBuilding three-column web page"); director.Construct(threeColumnBuilder); WebPage threeColumnWebPage = threeColumnBuilder.GetWebPage(); threeColumnWebPage.Show(); } }
弊
使用 Builder 设计模式的一个潜在缺点是,它可能导致生成大量代码,因为每个产品变型通常都有一个单独的 Concrete Builder 类。这会使代码更难维护和理解。
另一个缺点是,对于简单产品来说,Builder 模式可能有点过分,因为它增加了额外的抽象级别,并使代码更加复杂。在这种情况下,直接创建对象可能比使用生成器更简单。
值得注意的是,与任何设计模式一样,Builder 模式不是一个放之四海而皆准的解决方案,应根据正在开发的软件的特定需求适当使用。
结论
总之,Builder 设计模式是一种创建性设计模式,允许逐步构建复杂对象。它将构造过程与对象的表示分开,允许相同的构造过程创建不同的表示。当构造过程复杂且要构造的对象由多个部分组成时,生成器模式非常有用。它还可用于构造不可变的对象,并提供对构造过程的更高级别的控制。但是,它可能会导致生成大量代码,并且对于简单产品来说可能是矫枉过正的。与任何设计模式一样,根据正在开发的软件的特定需求适当地使用 Builder 模式非常重要。
下面是生成器模式可能有用的一些特定需求:
- 当构造过程复杂且要构造的对象由多个部分组成时,可以使用 Builder 模式来简化构造过程并使其更易于理解。
- 当构造过程需要高度灵活并能够生成对象的不同表示时,可以使用 Builder 模式将构造过程与对象的表示分开。
- 当要构造的对象是不可变的并且需要线程安全时,可以使用 Builder 模式逐步构造对象,确保在创建对象后不会对其进行修改。
- 当需要对构造过程进行高级别控制时,可以使用 Builder 模式来指定构造对象所需的确切步骤顺序。
- 当需要能够轻松地将新类型的产品添加到软件中时,Builder 模式可用于创建实现 Builder 接口的新混凝土生成器,并且可以以与现有混凝土生成器相同的方式使用。