推荐阅读:
当一个复杂对象由一些子对象构成,并且子对象的变化会导致复杂对象的修改。这时我们需要提供一种"封装机制"来隔离出"复杂对象的各个部分"的变化,从而保持系统中的"稳定构建算法"不随需求的改变而改变,这就是今天要给大家分享的建造者模式。
建造者模式(Builder Pattern)
建造者模式属于创建型模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式要素:
1、抽象建造者(Builder):给出一个抽象结论,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的对象部件的创建;
2、具体建造者(Concrete Builder):实现建造者接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。在构造过程完成后,提供产品的实例;
3、指导者(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建;
4、产品类(Product):需要创建的具体的复杂对象。
下面举个例子来为大家讲解一下吧。
命名空间建造者模式中包含Phone手机类充当产品类,Builder基类为抽象建造者,华为HF类、小米XM类、魅族MZ类。另外包含1个手机扩展类和1个指导者。本示例向大家演示3个不同的手机厂商在生产比较复杂的汽车时所采用的策略。
理清了这个逻辑过程之后,下面就具体看下如何用代码来表示这种现实生活中的逻辑过程:
1.创建抽象建造者Builder
public abstract class Builder {
protected phone = new Phone();//手机
public abstract void BuildCPU();//CPU
public abstract void BuildBattery();//电池
public abstract void BuildSpeaker();//扬声器
public abstract void BuildColor();//颜色
public virtual Phone GetPhone() {
return phone;
}
}
2.具体建造者(CPU,Battery,Speaker,Color)
public class HW : Builder {
public override void BuildCPU() {
phone.Carframe = "华为的处理器";
}
public override void BuildBattery() {
phone.Battery = 3000;
}
public override void BuildSpeaker() {
phone.Speaker= "华为的扬声器";
}
public override void BuildColor() {
phone.Color= "华为的专属颜色";
}
}
public class XM : Builder {
public override void BuildCPU() {
phone.Carframe = "小米的处理器";
}
public override void BuildBattery() {
phone.Battery = 3500;
}
public override void BuildSpeaker() {
phone.Speaker= "小米的扬声器";
}
public override void BuildColor() {
phone.Color= "小米的专属颜色";
}
}
public class MZ : Builder {
public override void BuildCPU() {
phone.Carframe = "魅族的处理器";
}
public override void BuildBattery() {
phone.Battery = 2500;
}
public override void BuildSpeaker() {
phone.Speaker= "魅族的扬声器";
}
public override void BuildColor() {
phone.Color= "魅族的专属颜色";
}
}
3.指导者Director
public class Director {
public void Construct(Builder builder) {
builder.BuildCPU();
builder.BuildBattery();
builder.BuildSpeaker();
builder.BuildColor();
}
}
4.一个扩展类
public static class Extentions {
public static string VehicleInfo(this Vehicle vehicle) {
var type = vehicle.GetType();
var properties = type.GetProperties();
var result = string.Empty;
foreach (var prop in properties) {
result +=
$"{prop.Name}:{prop.GetValue(vehicle, null)}{Environment.NewLine}";
}
return result;
}
}
5.调用方的代码,分别维持对指导者、建造者和手机的引用,接下来我们创建了3部手机。
public class Program {
private static Director _director = null;
private static List<Builder> _builders = null;
private static Phone _phone = null;
public static void Main(string[] args) {
_director = new Director();
_phone = new Phone ();
_builders = new List<Builder>() {
new HW(),
new XM(),
new MZ()
};
foreach (var builder in _builders) {
_director.Construct(builder);
_phone = builder.GetResult();
_phone .Print();
}
Console.ReadKey();
}
}
上面,我们介绍完了建造者模式的具体实现之后,最后让我们总结下建造模式的实现要点:
1.在建造者模式中,指挥者是直接与客户端打交道的,指挥者将客户端创建产品的请求划分为对各个部件的建造请求,再将这些请求委派到具体建造者角色,具体建造者角色是完成具体产品的构建工作的,却不为客户所知道。
2.。建造者模式主要用于“分步骤来构建一个复杂的对象”,其中“分步骤”是一个固定的组合过程,而复杂对象的各个部分是经常变化的(也就是说电脑的内部组件是经常变化的,这里指的的变化如硬盘的大小变了,CPU由单核变双核等)。
3.产品不需要抽象类,由于建造模式的创建出来的最终产品可能差异很大,所以不大可能提炼出一个抽象产品类。
4.在前面文章中介绍的抽象工厂模式解决了“系列产品”的需求变化,而建造者模式解决的是 “产品部分” 的需要变化。
5.由于建造者隐藏了具体产品的组装过程,所以要改变一个产品的内部表示,只需要再实现一个具体的建造者就可以了,从而能很好地应对产品组成组件的需求变化。