1、建造者模式简介
1.1>、定义
建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
1.2>、使用频率
中低
1.3>、原型模式应用
在软件系统中,有时候面临一个复杂对象的创建工作,该对象通常由各个部分子对象用一定的算法构成,或者按一定的步骤组合而成;这些算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求的变化而不断变化。
生活中的例子,要组装一台电脑,它的组装过程基本是不变的,都可以由主板、CPU、内存等按照某个稳定方式组合而成。然而主板、CPU、内存等零件本身都是可能多变的。将内存等这种易变的零件与电脑的其他部件分离,实现解耦合,则可以轻松实现电脑不断升级。
2、建造者模式结构
2.1>、结构图
2.2>、参与者
建造者模式参与者:
◊ Builder:为创建一个Product对象的各个部件指定抽象接口;
◊ ConcreteBuilder
° 实现Builder的接口以构造和装配该产品的各个部件
° 定义并明确它所创建的表示
° 提供一个检索Product的接口
◊ Director:构造一个使用Builder接口的对象;
◊ Product
° 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程
° 包含定义组成部件的类,包括将这些部件装配成最终产品的接口
在建造者模式中,Director规定了创建一个对象所需要的步骤和次序,Builder则提供了一些列完成这些步骤的方法,ConcreteBuilder给出了这些方法的具体实现,是对象的直接创建者。
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; } } }
3、建造者模式分析
介绍完了建造者模式的具体实现之后,让我们总结下建造模式的实现要点:
- 在建造者模式中,指挥者是直接与客户端打交道的,指挥者将客户端创建产品的请求划分为对各个部件的建造请求,再将这些请求委派到具体建造者角色,具体建造者角色是完成具体产品的构建工作的,却不为客户所知道。
- 建造者模式主要用于“分步骤来构建一个复杂的对象”,其中“分步骤”是一个固定的组合过程,而复杂对象的各个部分是经常变化的(也就是说电脑的内部组件是经常变化的,这里指的的变化如硬盘的大小变了,CPU由单核变双核等)。
- 产品不需要抽象类,由于建造模式的创建出来的最终产品可能差异很大,所以不大可能提炼出一个抽象产品类。
- 在前面文章中介绍的抽象工厂模式解决了“系列产品”的需求变化,而建造者模式解决的是 “产品部分” 的需要变化。
- 由于建造者隐藏了具体产品的组装过程,所以要改变一个产品的内部表示,只需要再实现一个具体的建造者就可以了,从而能很好地应对产品组成组件的需求变化。