建造者模式是一种较为复杂的创建型模式,它将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需知道所需建造者的类型即可。建造者模式关注如何逐步创建一个复杂的对象,不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,更换建造者或增加新的建造者非常方便,系统具有较好的扩展性。
建造者模式概述
建造者模式可以将部件本身和它们的组装过程分开,关注如何一步步创建一个包含多个组成部分的复杂对象,用户只需要指定复杂对象的类型即可得到该对象,而无须知道其内部的具体构造细节。
建造者模式的定义
建造者模式将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的结构
- Builder(抽象建造者): 它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类是BuilderX(),它们用于创建复杂对象的各个部件;另一类方法是GetResult(),它们用于返回复杂的对象。Builder既可以是抽象类,也可以是接口。
- ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确所创建的复杂对象,还可以提供一个方法返回创建好复杂产品对象。
- Product(产品):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
-
Direcotr(指挥者): 指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其Constructor()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。
建造者模式的实现

Product.cs
public class Product
{
public string PartA { get; set; }
public string PartB { get; set; }
public string PartC { get; set; }
}
AbstractBuilder.cs, 抽象建造者定义了创建方法和返回方法
public abstract class AbstractBuilder
{
// 创建产品对象
protected Product product = new Product();
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract void BuilderPartC();
// 返回产品对象
public Product GetResult()
{
return product;
}
}
ConcreteBuilder1.cs
public class ConcreteBuilder1: AbstractBuilder
{
public override void BuilderPartA()
{
product.PartA = "ConcreteBuilder1:A1";
}
public override void BuilderPartB()
{
product.PartB = "ConcreteBuilder1:B1";
}
public override void BuilderPartC()
{
product.PartC = "ConcreteBuilder1:C1";
}
}
Director.cs, 指挥者类主要有两个作用,一方面隔离了客户端与创建过程;另一方面控制产品对象的创建过程,包括某个BuilderX()方法是否被调用以及多个BuilderX()方法调用的先后次序等。
public class Director
{
private AbstractBuilder builder;
public Director(AbstractBuilder builder)
{
this.builder = builder;
}
public void SetBuilder(AbstractBuilder builder)
{
this.builder = builder;
}
// 产品构建与组装方法
public Product Construct()
{
builder.BuilderPartA();
builder.BuilderPartB();
builder.BuilderPartC();
return builder.GetResult();
}
}
Director深入讨论
省略Director
在某些情况下,为了简化系统结构,可以省略Director类,把Director和抽象建造者合并。更简单的方式,可以将Construct()参数去掉,直接调用Builder方法:
public abstract class AbstractBuilder
{
// 创建产品对象
protected static Product product = new Product();
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract void BuilderPartC();
// 返回产品对象
public Product GetResult()
{
return product;
}
// 方法一
public static Product Construct(AbstractBuilder builder)
{
builder.BuilderPartA();
builder.BuilderPartB();
builder.BuilderPartC();
return product;
}
// 方法二
public Product Construct()
{
this.BuilderPartA();
this.BuilderPartB();
this.BuilderPartC();
return product;
}
}
钩子函数的引用
建造者模式除了逐步构建一个复杂产品对象外,还可以通过Direcotor类来更加精细地控制产品地创建过程,例如增加一类称为钩子函数(Hook Method)的特殊方法来控制是否调用某个BuilderPartX()方法。钩子方法的返回类型通常为bool类型,方法名一般为IsXXX(),钩子方法定义在抽象建造者中。
public abstract class AbstractBuilder
{
// 创建产品对象
protected static Product product = new Product();
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract void BuilderPartC();
public virtual bool IsNeedBuildPartB()
{
return false;
}
// 返回产品对象
public Product GetResult()
{
return product;
}
}
此处定义了一个虚方法,在具体建造者中,可以根据需要重写该方法,使其返回实际需要的值,然后在构建过程中,使用该值进行构建。
建造者模式的优点
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
- 可以很方便地替换具体建造者或增加新的具体建造者
- 还可以更加精细地控制产品的创建过程
建造者模式的缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,并不适合使用建造者模式.
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本.
建造者模式的适用环境
- 需要生产的产品对象有复杂的内部结构,这些产品对象通常包含多个成员变量.
- 需要生产的产品对象的属性相互依赖,需要指定其生成顺序.
- 对象的创建过程独立于创建该对象的类.
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品.
如果觉得文章写得还行,请点个赞。如果想与我进一步交流,可以关注我的公众号或者加我的微信。


网友评论