C#中的Builder模式
设计模式中的Builder模式,又叫建造者模式,是一种常用的模式,它主要的作用是分离一个复杂对象的构建过程和复杂对象的表现形式,抽象出构建过程,这样可以使用相同的构建过程,配合依赖注入构建出不用的产品。
UML
其中有两点需要注意。
- Director和Builder之间是聚合关系而不是合成关系,暗示Director不需要对Builder的生命周期负责,Builder在外部创造并通过依赖注入的方式进入Director。
- 客户代码使用的时候可以通过Directory间接操作Builder,完成复杂对象的构造,不用直接调用Builder的各个方法。通过这样我们确保Directory统一了复杂对象的创造逻辑。
一个例子
考虑一下一个例子,我们创造一个房子,当然,房子有很多种,有别墅,平房,楼房等,但是抽象的看来,每个房子都需要一下几个步骤
- CreateWall
- CreateRoom
- CreateWindow
- CreateDoor
而一个房子大概也需要如下属性
- Wall
- Room
- Window
- Door
这样,我们试着来抽象出房子(在这里是我们的Product)和建造者接口。
public class House
{
public string Type { get; set; }
public House(string type)
{
Type = type;
}
}
很简单的一个类,仅仅一个属性,接着是创建者接口。
interface IHouseBuilder
{
void CreateWall();
void CreateRoom();
void CreateWindow();
void CreateDoor();
House GetHouse();
}
很简单,对吧?
接着我们试着来创造两个具体的创建者,分别创建平房和楼房。
class PingHouseBuilder : IHouseBuilder
{
public void CreateDoor()
{
Console.WriteLine("ping door");
}
public void CreateRoom()
{
Console.WriteLine("ping room");
}
public void CreateWall()
{
Console.WriteLine("ping wall");
}
public void CreateWindow()
{
Console.WriteLine("ping window");
}
public House GetHouse()
{
return new House("ping");
}
}
class LouHouseBuilder : IHouseBuilder
{
public void CreateDoor()
{
Console.WriteLine("lou door");
}
public void CreateRoom()
{
Console.WriteLine("lou room");
}
public void CreateWall()
{
Console.WriteLine("lou wall");
}
public void CreateWindow()
{
Console.WriteLine("lou window");
}
public House GetHouse()
{
return new House("lou");
}
}
这是两个相当简单的创建者,通过一些输出显示一些步骤的执行,现实生活中肯定不会那么简单,但是用作示例代码足够了,接下来是我们的Director。
class Director
{
IHouseBuilder _builder;
public Director(IHouseBuilder builder)
{
this._builder = builder;
}
public void Construct()
{
_builder.CreateWall();
_builder.CreateRoom();
_builder.CreateWindow();
_builder.CreateDoor();
}
}
从上面看出,通过Construct方法,固定得调用Builder里面的各个步骤。最后看看客户代码。
IHouseBuilder builder = new PingHouseBuilder();
Director director = new Director(builder);
director.Construct();
var house = builder.GetResult();
在上面的代码中,客户代码负责创建builder实例,实例化Director,调用construct,最后通过builder得到创建出来的结果。
如果需要创建不同的House,只需要用替换Director里面的builder即可,其他步骤都可以保持不动,这样就实现了解耦。
和TemplateMethod模式的比较
乍一看,Builder模式和TemplateMethod模式比较相似,都是固定了某些子步骤,方便客户代码能够以固定的顺序或者逻辑来使用子步骤,同时两种模式都能方便再定义子步骤。
但它们之间也有一些区别,主要在于两点。
- Builder模式是创造模式,主要使用的场景是创造新对象,特别是复杂对象;TemplateMethod模式是行为模式,主要是通过固定子步骤逻辑来统一实现某种行为,比如,在Save之前的SaveCheck等。
- Builder模式使用依赖注入达到具体Builder和Director的解耦;而TemplateMethod通过继承抽象类达到再定义某些子步骤的效果。
综上,在选择这两种模式的时候,要综合考虑使用的场景再做出决定。