存在目地:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
应用场景:在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?
应用实例:.NET环境下的字符串处理StringBuilder,这是一种简化了的建造者模式。
实现方式:
using System;
using System.Collections;
// 指导者角色,与客户端打交道,调用具体建造者角色以创建产品对象
class Director
{
// Methods
public void Construct( Builder builder )
{
builder.BuildPartA();
builder.BuildPartB();
}
}
// 建造者角色,抽象接口,规范产品对象的各个组成成分的建造
abstract class Builder
{
// Methods
abstract public void BuildPartA();
abstract public void BuildPartB();
abstract public Product GetResult();
}
// 具体建造者,创建具体产品的实例
class ConcreteBuilder1 : Builder
{
// Fields
private Product product = new Product();
// Methods
override public void BuildPartA()
{
product.Add( "PartA" );
}
override public void BuildPartB()
{
product.Add( "PartB" );
}
override public Product GetResult()
{
return product;
}
}
// 具体建造者
class ConcreteBuilder2 : Builder
{
// Fields
private Product product = new Product();
// Methods
override public void BuildPartA()
{
product.Add( "PartX" );
}
override public void BuildPartB()
{
product.Add( "PartY" );
}
override public Product GetResult()
{
return product;
}
}
// 产品角色,便是需要建造的复杂对象
class Product
{
// Fields
ArrayList parts = new ArrayList();
// Methods
public void Add( string part )
{
parts.Add( part );
}
public void Show()
{
Console.WriteLine( " Product Parts -------" );
foreach( string part in parts )
{ Console.WriteLine( part ); }
}
}
// 客户端调用
public class Client
{
public static void Main( string[] args )
{
// 创建指导者和具体建造者
Director director = new Director( );
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
// 由指导者调用具体建造者创建产品对象
director.Construct( b1 );
Product p1 = b1.GetResult();
p1.Show();
director.Construct( b2 );
Product p2 = b2.GetResult();
p2.Show();
}
}
首先由客户端创建指导者和具体建造者对象,然后由指导者操作具体建造者对象来创建产品,最后由建造者将产品返还给客户端。
特别地,当系统中只有一个具体建造者时,可以省略抽象建造者和指导者角色,让该具体建造者自己扮演指导者与建造者双重角色,省略后代码如下:
// 建造者
public class Builder
{
private Product product = new Product();
public void BuildPartA()
{
//
}
public void BuildPartB()
{
//
}
public Product GetResult()
{
return product;
}
public void Construct()
{
BuildPartA();
BuildPartB();
}
}
// 客户端调用
public class Client
{
private static Builder builder;
public static void Main()
{
builder = new Builder();
builder.Construct();
Product product = builder.GetResult();
}
}
适用性:
1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。
参考资料:
Erich Gamma《设计模式可复用面向对象软件的基础》