问题:
在软件系统中,有时面临着一个复杂对象的创建工作,通常是由很多其他的对象按一定的规则顺序组合而成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的规则是相对稳定(结构和顺序)。这时候我们需要把这个复杂对象的创建过程和这个对象的表示(展示)分离开来,使得可以使用同样的构建过程创建不同的对象 表示。
定义:
将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
意图:
提供一个建造者Builder对象,他规定了创建一个复杂对象需要的部件,通过Director指定的创建规则,调用Builder中的具体部件,并指挥Builder返回一个具体的对象。
参与者:
•建造者(Builder):
为创建一个产品对象的各个部件指定抽象接口。一般会有两种接口方法,一种接口用于规范产品的各个部分的组成,第二种接口用于返回建造后的产品。
•具体建造者(ConcreteBuilder):
实现Builder的接口,按具体的规则组合复杂产品的各个部件,以及提供一个返回产品的接口。
•指挥者(Director):
指挥并构造一个使用Builder接口的对象。他只是在按照固定的流程规则将对象组合在一起。不关心组合产品的结果(复杂对象),和细节(子对象)。
•产品(Product):
表示被构造的复杂对象。
UML:
实例说明:
诺基亚手机工厂
公司定义了手机的生产步骤,交给生产部生产。
uml图如下:
代码:
/// Builder 定义手机生产需要的组件(步骤)
/// </summary>
public abstract class BuilderPhone
{
public abstract void BuildMb();
public abstract void BuildCpu();
public abstract void SetSystem();
public abstract void Test();
public abstract Phone GetPhone();
}
/// <summary>
/// N8手机生产具体生产
/// </summary>
public class BuilderN8 : BuilderPhone
{
Phone n8;
public BuilderN8()
{
n8 = new Phone();
n8.PhoneName = "N8";
}
public override void BuildMb()
{
n8.Mb = "N8_2.0";
System.Console.WriteLine("N8主板安装完成!");
}
public override void BuildCpu()
{
n8.Cpu = "ARM_C28";
System.Console.WriteLine("N8 CPU 安装完成!");
}
public override void SetSystem()
{
n8.System = "塞班S60第三版";
System.Console.WriteLine("N8 系统 安装完成!");
}
public override void Test()
{
n8.TestStatus = true;
System.Console.WriteLine("N8 测试完成!");
}
public override Phone GetPhone()
{
return n8;
}
}
/// <summary>
/// 指挥者 指挥 一个手机的 创建步骤 (是,先安装内存 还是先安装主板。。。)
/// </summary>
public class DirectorBuilderPhone
{
public void Construct(BuilderPhone builderPhone)
{
//先安装主板
builderPhone.BuildMb();
//安装CPU
builderPhone.BuildCpu();
//安装系统
builderPhone.SetSystem();
//测试
builderPhone.Test();
}
}
/// <summary>
/// 具体的产品
/// </summary>
public class Phone
{
public String PhoneName { get; set; }
public String Mb { get; set; }
public String Cpu { get; set; }
public String System { get; set; }
public bool TestStatus { get; set; }
}
/// <summary>
/// 客户端测试代码
/// </summary>
public void BuilderTest()
{
//实例化一个指挥者
DirectorBuilderPhone dbp = new DirectorBuilderPhone();
//建造者
BuilderPhone bp = new BuilderN8();
//建造
dbp.Construct(bp);
//返回产品
bp.GetPhone();
}
优点:
•用户只需要指定要建造的类型就可以得到它们,而具体的建造过程和细节不需要知道。
•建造代码与表示相分离,如果要改变一个产品的内部表示,只要再定义一个新的具体的建造者就可以了。
•建造过程由指挥者来控制,建造细节由一个抽象类来控制,对于实现建造细节的具体类来说,不会遗漏某一个步骤。
缺点:
•产品的构造组件被定义在Builder,增加新的产品的一个细节需要修改Builder,违背了“开闭原则”。
应用情景:
•当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
•当复杂对象的部件相对稳定,不会发生变化时。
PS:
•Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。