建造者模式(Builder Pattern)

1、 建造者(Builder)模式

建造者模式(Builder)将复杂的构建与其表示相分离,使得一样的构建过程能够建立不一样的表示。在软件系统中,有时候面临一个复杂对象的建立工做,该对象一般由各个部分子对象用必定的算法构成,或者按必定的步骤组合而成;这些算法和步骤是稳定的,而构成这个对象的子对象却常常因为需求的变化而不断变化。算法

 

2、建造者模式的结构

 

建造者模式参与者:设计模式

  ◊ Builder:为建立一个Product对象的各个部件指定抽象接口;ide

  ◊ ConcreteBuilderui

    ° 实现Builder的接口以构造和装配该产品的各个部件spa

    ° 定义并明确它所建立的表示设计

    ° 提供一个检索Product的接口code

  ◊ Director:构造一个使用Builder接口的对象;对象

  ◊ Productblog

    ° 表示被构造的复杂对象。ConcreteBuilder建立该产品的内部表示并定义它的装配过程接口

    ° 包含定义组成部件的类,包括将这些部件装配成最终产品的接口

  在建造者模式中,Director规定了建立一个对象所须要的步骤和次序,Builder则提供了一些列完成这些步骤的方法,ConcreteBuilder给出了这些方法的具体实现,是对象的直接建立者。

 

3、 示意性源代码

例如一个采购系统中,若是须要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象,它是由CPU、主板、硬盘、显卡、机箱等组装而成的,若是此时让采购员一台一台电脑去组装的话真是要累死采购员了,这里就能够采用建造者模式来解决这个问题,咱们能够把电脑的各个组件的组装过程封装到一个建造者类对象里,建造者只要负责返还给客户端所有组件都建造完毕的产品对象就能够了。然而现实生活中也是如此的,若是公司要采购一批电脑,此时采购员不可能本身去买各个组件并把它们组织起来,此时采购员只须要像电脑城的老板说本身要采购什么样的电脑就能够了,电脑城老板天然会把组装好的电脑送到公司。下面就以这个例子来展开建造者模式的介绍。

在这个例子中,电脑城的老板是直接与客户(也就是指采购员)联系的,然而电脑的组装是由老板指挥装机人员去把电脑的各个部件组装起来,真真负责建立产品(这里产品指的就是电脑)的人就是电脑城的装机人员。理清了这个逻辑过程以后,下面就具体看下如何用代码来表示这种现实生活中的逻辑过程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


/// <summary>
/// 以组装电脑为例子
/// 每台电脑的组成过程都是一致的,可是使用一样的构建过程能够建立不一样的表示(便可以组装成不同的电脑,配置不同)
/// 组装电脑的这个场景就能够应用建造者模式来设计
/// </summary>
namespace 设计模式之建造者模式
{
    /// <summary>
    /// 客户类
    /// </summary>
    class Customer
    {
        static void Main(string[] args)
        {
            // 客户找到电脑城老板说要买电脑,这里要装两台电脑
            // 建立指挥者和构造者
            Director director = new Director();
            Builder b1 = new ConcreteBuilder1();
            Builder b2 = new ConcreteBuilder2();

            // 老板叫员工去组装第一台电脑
            director.Construct(b1);

            // 组装完,组装人员搬来组装好的电脑
            Computer computer1 = b1.GetComputer();
            computer1.Show();

            // 老板叫员工去组装第二台电脑
            director.Construct(b2);
            Computer computer2 = b2.GetComputer();
            computer2.Show();

            Console.Read();
        }
    }

    /// <summary>
    /// 小王和小李难道会自愿地去组装嘛,谁不想休息的,这必须有一我的叫他们去组装才会去的
    /// 这我的固然就是老板了,也就是建造者模式中的指挥者
    /// 指挥建立过程类
    /// </summary>
    public class Director
    {
        // 组装电脑
        public void Construct(Builder builder)
        {
            builder.BuildPartCPU();
            builder.BuildPartMainBoard();
        }
    }

    /// <summary>
    /// 电脑类
    /// </summary>
    public class Computer
    {
        // 电脑组件集合
        private IList<string> parts = new List<string>();

        // 把单个组件添加到电脑组件集合中
        public void Add(string part)
        {
            parts.Add(part);
        }

        public void Show()
        {
            Console.WriteLine("电脑开始在组装.......");
            foreach (string part in parts)
            {
                Console.WriteLine("组件"+part+"已装好");
            }

            Console.WriteLine("电脑组装好了");
        }
    }

    /// <summary>
    /// 抽象建造者,这个场景下为 "组装人" ,这里也能够定义为接口
    /// </summary>
    public abstract class Builder
    {
        // 装CPU
        public abstract void BuildPartCPU();
        // 装主板
        public abstract void BuildPartMainBoard();
        
        // 固然还有装硬盘,电源等组件,这里省略

        // 得到组装好的电脑
        public abstract Computer GetComputer();
    }

    /// <summary>
    /// 具体建立者,具体的某我的为具体建立者,例如:装机小王啊
    /// </summary>
    public class ConcreteBuilder1 : Builder
    {
        Computer computer = new Computer();
        public override void BuildPartCPU()
        {
            computer.Add("CPU1");
        }

        public override void BuildPartMainBoard()
        {
            computer.Add("Main board1");
        }

        public override Computer GetComputer()
        {
            return computer;
        }
    }

    /// <summary>
    /// 具体建立者,具体的某我的为具体建立者,例如:装机小李啊
    /// 又装另外一台电脑了
    /// </summary>
    public class ConcreteBuilder2 : Builder
    {
        Computer computer = new Computer();
        public override void BuildPartCPU()
        {
            computer.Add("CPU2");
        }

        public override void BuildPartMainBoard()
        {
            computer.Add("Main board2");
        }

        public override Computer GetComputer()
        {
            return computer;
        }
    }
}

上面代码中都有详细的注释代码,这里就不过多解释,你们能够参考代码和注释来与现实生活中的例子作对比,下图展现了上面代码的运行结果:

建造者模式的定义和类图

介绍完了建造者模式的具体实现以后,下面具体看下建造者模式的具体定义是怎样的。

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。

建造者模式使得建造代码与表示代码的分离,可使客户端没必要知道产品内部组成的细节,从而下降了客户端与具体产品之间的耦合度,下面经过类图来帮助你们更好地理清建造者模式中类之间的关系。

 

 

4、建造者模式的分析

介绍完了建造者模式的具体实现以后,让咱们总结下建造模式的实现要点:

  1. 在建造者模式中,指挥者是直接与客户端打交道的,指挥者将客户端建立产品的请求划分为对各个部件的建造请求,再将这些请求委派到具体建造者角色,具体建造者角色是完成具体产品的构建工做的,却不为客户所知道。
  2. 建造者模式主要用于“分步骤来构建一个复杂的对象”,其中“分步骤”是一个固定的组合过程,而复杂对象的各个部分是常常变化的(也就是说电脑的内部组件是常常变化的,这里指的的变化如硬盘的大小变了,CPU由单核变双核等)。
  3. 产品不须要抽象类,因为建造模式的建立出来的最终产品可能差别很大,因此不大可能提炼出一个抽象产品类。
  4. 在前面文章中介绍的抽象工厂模式解决了“系列产品”的需求变化,而建造者模式解决的是 “产品部分” 的须要变化。
  5. 因为建造者隐藏了具体产品的组装过程,因此要改变一个产品的内部表示,只须要再实现一个具体的建造者就能够了,从而能很好地应对产品组成组件的需求变化。

5、.NET 中建造者模式的实现

前面的设计模式在.NET类库中都有相应的实现,那在.NET 类库中,是否也存在建造者模式的实现呢? 然而对于疑问的答案是确定的,在.NET 类库中,System.Text.StringBuilder(存在mscorlib.dll程序集中)就是一个建造者模式的实现。不过它的实现属于建造者模式的演化,此时的建造者模式没有指挥者角色和抽象建造者角色,StringBuilder类即扮演着具体建造者的角色,也同时扮演了指挥者和抽象建造者的角色,此时建造模式的实现以下:

/// <summary>
    /// 建造者模式的演变
    /// 省略了指挥者角色和抽象建造者角色
    /// 此时具体建造者角色扮演了指挥者和建造者两个角色
    /// </summary>
    public class Builder
    {
        // 具体建造者角色的代码
        private Product product = new Product();
        public void BuildPartA()
        {
            product.Add("PartA");
        }
        public void BuildPartB()
        {
            product.Add("PartB");
        }
        public Product GetProduct()
        {
            return product;
        }
        // 指挥者角色的代码
        public void Construct()
        {
            BuildPartA();
            BuildPartB();
        }
    }

    /// <summary>
    /// 产品类
    /// </summary>
    public class Product
    {
        // 产品组件集合
        private IList<string> parts = new List<string>();

        // 把单个组件添加到产品组件集合中
        public void Add(string part)
        {
            parts.Add(part);
        }

        public void Show()
        {
            Console.WriteLine("产品开始在组装.......");
            foreach (string part in parts)
            {
                Console.WriteLine("组件" + part + "已装好");
            }

            Console.WriteLine("产品组装完成");
        }
    }

    // 此时客户端也要作相应调整
    class Client 
    {
        private static Builder builder;
        static void Main(string[] args)
        {
            builder = new Builder();
            builder.Construct();
            Product product = builder.GetProduct();
            product.Show();
            Console.Read();
        }
    }

StringBuilder类扮演着建造string对象的具体建造者角色,其中的ToString()方法用来返回具体产品给客户端(至关于上面代码中GetProduct方法)。其中Append方法用来建立产品的组件(至关于上面代码中BuildPartA和BuildPartB方法),由于string对象中每一个组件都是字符,因此也就不须要指挥者的角色的代码(指的是Construct方法,用来调用建立每一个组件的方法来完成整个产品的组装),由于string字符串对象中每一个组件都是同样的,都是字符,因此Append方法也充当了指挥者Construct方法的做用。

总结

到这里,建造者模式的介绍就结束了,建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的一样的构建过程能够建立不一样的表示。建造者模式的本质是使组装过程(用指挥者类进行封装,从而达到解耦的目的)和建立具体产品解耦,使咱们不用去关心每一个组件是如何组装的。

相关文章
相关标签/搜索