一、简介(Brief Introduction)
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。
二、模式分析(Analysis)
Builder是为创建一个Product对象的各个部件指定的抽象接口。
ConcreteBuilder是具体建造者,实现Builder接口,构造和装配各个部件。
Director是构建一个使用Builder接口的对象。
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
例子1:买肯德基
典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡、炸鸡、可乐和玩具车)。这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的。
客户端:顾客,想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供顾客选择。
指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。
建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。
产品角色:最后的套餐,所有的东西放在同一个盘子里面。
三、案例分析(Example)
namespace 建造者模式
1、客户端
class Program
{
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();
Console.Read();
}
}
2、Product类,由多个部件组成
class Product
{
IList<string> parts = new List<string>();
//添加产品部件
public void Add(string part)
{
parts.Add(part);
}
//列举所有的产品部件
public void Show()
{
Console.WriteLine("\n产品 创建----");
foreach (string part in parts)
{
Console.WriteLine(part);
}
}
}
3
、Builder类----抽象建造这类,确定产品有两个部件PartA和PartB组成,并声明一个得到产品建造后果的方法GetResult;
abstract class Builder
{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
}
4、ConcreteBuilder1类---具体建造这类
class ConcreteBuilder1 : Builder
{
private Product product = new Product();
public override void BuildPartA()
{
product.Add("部件A");
}
public override void BuildPartB()
{
product.Add("部件B");
}
public override Product GetResult()
{
return product;
}
}
5、ConcreteBuilder2类
class ConcreteBuilder2 : Builder
{
private Product product = new Product();
public override void BuildPartA()
{
product.Add("部件X");
}
public override void BuildPartB()
{
product.Add("部件Y");
}
public override Product GetResult()
{
return product;
}
}
6、Director类--指挥者
class Director
{
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
}
四、解决的问题(What To Solve)
1 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2 当构造过程必须允许被构造的对象有不同表示时。
五、优缺点(Advantage and Disadvantage)
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以基需要改变一个产品的内部表示,只需要再定义一个具体的指挥者就可以。它主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
六、联系(Link)
(一)与装饰模式的区别
装饰模式
1 装饰物与被装饰物继承自同一组件类,组件对象均可由装饰物在外部(客户代码中)按顺序装饰;
2 各装饰物记住自己装饰了谁,其功能函数除了实现自己的功能外,还需要调用被自己装饰的组件的功能函数;
3 装饰模式针对构建过程不稳定的情况。
建造者模式
1 被建造对象集成一个成员组成稳定的接口,并对成员内容做具体实现;
2 被创建对象的成员有一个指挥类稳定的按顺序建造,指挥类隔离建造过程及客户代码;
3 客户代码使用指挥类生成被创建对象;
4 建造者模式针对建造过程十分稳定的情况。
(二)与工厂模式的区别
总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。
与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
七、总结(Summary)
建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。