一、概述
在软件系统中,把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了类的逻辑。它把一个复杂对象的构造过程从对象的表示中分离出来了,其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。它强调的是产品构造过程。
二、意图
将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
三、Builder模式的结构
![](https://images.cnblogs.com/cnblogs_com/feipeng/Pic11.jpg)
Builder:为创建Product对象的各个部件指定抽象接口。
ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
Director:构造一个使用Builer接口的对象。
Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,以及将这些部件装配成最终产品的接口。
四、举例:
我们用KFC套餐为例,KFC中存在以下对象,各种食物Product,有收银员Director,可配置套餐菜单接口(主食+零食+饮料)Builder,具体套餐搭配ConcreteBuilder。
1. 首先给定可配置套餐菜单接口(主食+零食+饮料)Builder:
abstract public class Builder { // BuildPartA,BuildPartB,BuildPartC具体的套餐方法 abstract public void BuildPartA(); abstract public void BuildPartB(); abstract public void BuildPartC(); abstract public Product GetResult(); }
2.我们需要KFC的产品:
public class Product { ArrayList parts = new ArrayList(); public void Add(string part) { parts.Add(part); } public void Show() { Console.WriteLine(" Product Parts -------"); foreach (string part in parts) Console.WriteLine(part); } }
3. 然后,我们给出具体套餐搭配ConcreteBuilderA:
public class ConcreteBuilderA:Builder { private Product product; // Methods override public void BuildPartA() { product = new Product(); product.Add("麦香鸡腿堡"); } override public void BuildPartB() { product.Add("加冰可乐"); } override public void BuildPartC() { product.Add("大薯条"); } override public Product GetResult() { return product; } }
4. 然后,我们给出具体套餐搭配ConcreteBuilderB:
public class ConcreteBuilderB:Builder { private Product product; // Methods override public void BuildPartA() { product = new Product(); product.Add("香辣鸡腿堡"); } override public void BuildPartB() { product.Add("可乐不加冰"); } override public void BuildPartC() { product.Add("小薯条"); } public override Product GetResult() { return product; } }
5. 现在我们需要一个收银员Director:
public class Director { public void Construct(Builder builder) { builder.BuildPartA(); builder.BuildPartB(); builder.BuildPartC(); } }
6. 最后我们完成Client购买KFC套餐:
class Program { static void Main(string[] args) { Director director = new Director(); Builder b1 = new ConcreteBuilderA(); Builder b2 = new ConcreteBuilderB(); director.Construct(b1); Product p1 = b1.GetResult(); p1.Show(); director.Construct(b2); Product p2 = b2.GetResult(); p2.Show(); Console.ReadKey(); } }
这样Client分别买了两种不同的套餐,Client只需要让收款员知道你需要那种套餐即可,不需要了解具体套餐是如何实现的。
五、优点:
1.建造者模式的“加工工艺”是暴露的,这样使得建造者模式更加灵活。
2.解耦了组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。--上面对KFC的分析可以很清楚的看出这点。
六、适用环境:
1.需要生成的产品对象有复杂的内部结构。
2.需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3.在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
参考文献:
《.NET应用架构设计原则、模式与实践》 王洋 著