设计模式笔记——生成器模式(Builder Pattern)

一、概述
在软件系统中,把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了类的逻辑。它把一个复杂对象的构造过程从对象的表示中分离出来了,其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。它强调的是产品构造过程。
 
二、意图
将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
 
三、Builder模式的结构
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应用架构设计原则、模式与实践》 王洋 著
 
原文地址:https://www.cnblogs.com/Abel-Zhang/p/BuilderPattern.html