1、引言
今天咱们要讲讲Builder模式,也就是建造者模式,固然也有叫生成器模式的,英文名称是Builder Pattern。在现实生活中,咱们常常会遇到一些构成比较复杂的物品,好比:电脑,它就是一个复杂的物品,它主要是由CPU、主板、硬盘、显卡、机箱等组装而成的。手机固然也是复杂物品,由主板,各类芯片,RAM 和ROM 摄像头之类的东西组成。可是不管是电脑仍是手机,他们的组装过程是固定的,就拿手机来讲,组装流水线是固定的,不变的,可是把不一样的主板和其余组件组装在一块儿就会生产出不一样型号的手机。那么在软件系统中是否是也会存在这样的对象呢?答案是确定的。在软件系统中咱们也会遇到相似的复杂对象,而且这个复杂对象的各个部分按照必定的算法组合在一块儿,此时该对象的建立工做就可使用Builder模式了,下面我就来详细看看这个模式吧。
2、建造者模式的详细介绍
2.一、动机(Motivate)
在软件系统中,有时候面临着“一个复杂对象”的建立工做,其一般由各个部分的子对象用必定的算法构成;因为需求的变化,这个复杂对象的各个部分常常面临着剧烈的变化,可是将它们组合在一块儿的算法却相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?
2.二、意图(Intent)
将一个复杂对象的构建与其表示相分离,使得一样的构建过程能够建立不一样的表示。 ——《设计模式》GoF
2.三、结构图(Structure)
2.四、模式的组成
(1)、抽象建造者角色(Builder):为建立一个Product对象的各个部件指定抽象接口,以规范产品对象的各个组成成分的建造。通常而言,此角色规定要实现复杂对象的哪些部分的建立,并不涉及具体的对象部件的建立。
(2)、具体建造者(ConcreteBuilder)
1)实现Builder的接口以构造和装配该产品的各个部件。即实现抽象建造者角色Builder的方法。
2)定义并明确它所建立的表示,即针对不一样的商业逻辑,具体化复杂对象的各部分的建立
3) 提供一个检索产品的接口
4) 构造一个使用Builder接口的对象即在指导者的调用下建立产品实例
(3)、指导者(Director):调用具体建造者角色以建立产品对象的各个部分。指导者并无涉及具体产品类的信息,真正拥有具体产品的信息是具体建造者对象。它只负责保证对象各部分完整建立或按某种顺序建立。
(4)、产品角色(Product):建造中的复杂对象。它要包含那些定义组件的类,包括将这些组件装配成产品的接口。
2.5 建筑者模式的具体实现
如今人们生活水平都提升了,家家都有了家庭轿车,那今天咱们就以汽车组装为例来讲明Builder模式的实现。
算法
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 7 /// <summary> 8 /// 如今人们的生活水平都提升了,有钱了,我今天就以汽车组装为例子 9 /// 每台汽车的组装过程都是一致的,因此咱们使用一样的构建过程能够建立不一样的表示(便可以组装成不一样型号的汽车,不能像例子这样,一会别克,一会奥迪的) 10 /// 组装汽车、电脑、手机、电视等等负责对象的这些场景均可以应用建造者模式来设计 11 /// </summary> 12 namespace 设计模式之建造者模式 13 { 14 /// <summary> 15 /// 客户类 16 /// </summary> 17 class Customer 18 { 19 static void Main(string[] args) 20 { 21 Director director = new Director(); 22 Builder buickCarBuilder = new BuickBuilder(); 23 Builder aoDiCarBuilder = new AoDiBuilder(); 24 25 director.Construct(buickCarBuilder); 26 27 //组装完成,我来驾驶别克了 28 Car buickCar = buickCarBuilder.GetCar(); 29 buickCar.Show(); 30 31 // 我老婆就要奥迪了,她比较喜欢大品牌 32 director.Construct(aoDiCarBuilder); 33 Car aoDiCar = aoDiCarBuilder.GetCar(); 34 aoDiCar.Show(); 35 36 Console.Read(); 37 } 38 } 39 40 /// <summary> 41 /// 这个类型才是组装的,Construct方法里面的实现就是建立复杂对象固定算法的实现,该算法是固定的,或者说是相对稳定的 42 /// 这我的固然就是老板了,也就是建造者模式中的指挥者 43 /// </summary> 44 public class Director 45 { 46 // 组装汽车 47 public void Construct(Builder builder) 48 { 49 builder.BuildCarDoor(); 50 builder.BuildCarWheel(); 51 builder.BuildCarEngine(); 52 } 53 } 54 55 /// <summary> 56 /// 汽车类 57 /// </summary> 58 public sealed class Car 59 { 60 // 汽车部件集合 61 private IList<string> parts = new List<string>(); 62 63 // 把单个部件添加到汽车部件集合中 64 public void Add(string part) 65 { 66 parts.Add(part); 67 } 68 69 public void Show() 70 { 71 Console.WriteLine("汽车开始在组装......."); 72 foreach (string part in parts) 73 { 74 Console.WriteLine("组件" + part + "已装好"); 75 } 76 77 Console.WriteLine("汽车组装好了"); 78 } 79 } 80 81 /// <summary> 82 /// 抽象建造者,它定义了要建立什么部件和最后建立的结果,可是不是组装的的类型,切记 83 /// </summary> 84 public abstract class Builder 85 { 86 // 建立车门 87 public abstract void BuildCarDoor(); 88 // 建立车轮 89 public abstract void BuildCarWheel(); 90 //建立车引擎 91 public abstract void BuildCarEngine(); 92 // 固然还有部件,大灯、方向盘等,这里就省略了 93 94 // 得到组装好的汽车 95 public abstract Car GetCar(); 96 } 97 98 /// <summary> 99 /// 具体建立者,具体的车型的建立者,例如:别克 100 /// </summary> 101 public sealed class BuickBuilder : Builder 102 { 103 Car buickCar = new Car(); 104 public override void BuildCarDoor() 105 { 106 buickCar.Add("Buick's Door"); 107 } 108 109 public override void BuildCarWheel() 110 { 111 buickCar.Add("Buick's Wheel"); 112 } 113 114 public override void BuildCarEngine() 115 { 116 buickCar.Add("Buick's Engine"); 117 } 118 119 public override Car GetCar() 120 { 121 return buickCar; 122 } 123 } 124 125 /// <summary> 126 /// 具体建立者,具体的车型的建立者,例如:奥迪 127 /// </summary> 128 public sealed class AoDiBuilder : Builder 129 { 130 Car aoDiCar = new Car(); 131 public override void BuildCarDoor() 132 { 133 aoDiCar.Add("Aodi's Door"); 134 } 135 136 public override void BuildCarWheel() 137 { 138 aoDiCar.Add("Aodi's Wheel"); 139 } 140 141 public override void BuildCarEngine() 142 { 143 aoDiCar.Add("Aodi's Engine"); 144 } 145 146 public override Car GetCar() 147 { 148 return aoDiCar; 149 } 150 } 151 }
上面代码中都有详细的注释代码,这里就不过多解释。
3、建造者模式的实现要点
在建造者模式中,指挥者是直接与客户端打交道的,指挥者将客户端建立产品的请求划分为对各个部件的建造请求,再将这些请求委派到具体建造者角色,具体建造者角色是完成具体产品的构建工做的,却不为客户所知道。 建造者模式主要用于“分步骤来构建一个复杂的对象”,其中“分步骤”是一个固定的组合过程,而复杂对象的各个部分是常常变化的。 产品不须要抽象类,因为建造模式的建立出来的最终产品可能差别很大,因此不大可能提炼出一个抽象产品类。 在前面文章中介绍的抽象工厂模式解决了“系列产品”的需求变化,而建造者模式解决的是 “产品部分” 的须要变化。 因为建造者隐藏了具体产品的组装过程,因此要改变一个产品的内部表示,只须要再实现一个具体的建造者就能够了,从而能很好地应对产品组成组件的需求变化。
3.1】、建造者模式的优势:
(1)、使用建造者模式可使客户端没必要知道产品内部组成的细节。
(2)、具体的建造者类之间是相互独立的,容易扩展。
(3)、因为具体的建造者是独立的,所以能够对建造过程逐步细化,而不对其余的模块产生任何影响。
3.2】、建造者模式的缺点:
(1)、产生多余的Build对象以及Dirextor类。
3.3】、建立者模式的使用场景:
(1)、当建立复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
(2)、相同的方法,不一样的执行顺序,产生不一样的事件结果时。
(3)、多个部件或零件,均可以装配到一个对象中,可是产生的运行结果又不相同时。
(4)、产品类很是复杂,或者产品类中的调用顺序不一样产生了不一样的效能。
(5)、建立一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,可是对象的内部组成构件面临着复杂的变化。
4、.NET 中建造者模式的实现
在微软的类库里面大量使用了设计模式,若是要想学习设计模式,仔细看看微软的类库是颇有帮助的。今天的设计模式在FCL里面也有实现,该类型的名字就是System.Text.StringBuilder(存在mscorlib.dll程序集中),它就是一个建造者模式的实现,从名称也能够看出来。不过它的实现属于建造者模式的演化,此时的建造者模式没有指挥者角色和抽象建造者角色,StringBuilder类即扮演着具体建造者的角色,也同时扮演了指挥者和抽象建造者的角色,StringBuilder类扮演着建造string对象的具体建造者角色,其中的ToString()方法用来返回具体产品给客户端(至关于上面代码中GetProduct方法)。其中Append方法用来建立产品的组件(至关于上面代码中BuildPartA和BuildPartB方法),由于string对象中每一个组件都是字符,因此也就不须要指挥者的角色的代码(指的是Construct方法,用来调用建立每一个组件的方法来完成整个产品的组装),由于string字符串对象中每一个组件都是同样的,都是字符,因此Append方法也充当了指挥者Construct方法的做用。
5、总结
今天就到这里了,还须要重申的是,学习设计模式不能死学,就像StringBuilder同样,他和Gof23种设计模式中定义的情形有很大的不一样,可是它也是Builder模式,由于它们要解决的问题和使用场景是吻合的。咱们写代码的时候,不要太居于形式,要看使用的契机和模式是否吻合,根据具体的状况咱们的模式也会发生变化。当咱们看得越多,写的越多时候,你的变化就越天然了。
今天是2017年9月30日,明天就是国庆了,10月4日又是中秋,我在此祝你们节日快乐,工做顺利。我也要休息几天了,暂时就不写东西了。设计模式