Head First 设计模式 16-生成器模式
生成器模式(Builder Pattern)封装一个产品的构造过程,并允许按步骤构造
这种模式在 ORM(Object Relational Mapping 对象关系映射)框架的查询中经常能够遇到,很多框架都会提供类似 SqlBuilder 的功能。
书中以“主题公园”为例,通过生成器创建你的行程计划。其类图如下:
客户端采用类似下面的方式,按照生成器的规则创建假期计划。
csharp
AbstarctBuilder builder = new VacationBuilder();
builder.BuildDay(new DateTime(2020, 1, 1))
.AddHotel("葛雷巴旅馆")
.AddReservation("棒球比赛")
.AddSpecialEvent("拨打接听付费电话")
.AddTickets(new string[] { "《美丽人生》电影票", "张学友演唱会票" });
builder.BuildDay(new DateTime(2020, 1, 2))
.AddHotel("葛雷巴旅馆")
.AddReservation("棒球比赛决赛")
.AddSpecialEvent("继续拨打接听付费电话");
Console.WriteLine(builder.GetVacationPlanner());
优点
- 将一个复杂对象的创建过程封装起来。
- 允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)。
- 向客户隐藏产品内部的实现。
- 产品的实现可以被替换,因为客户只看到一个抽象的接口。
用途和缺点
- 经常被用来创建组合接口。
- 与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多的领域知识。
示例代码
AbstarctBuilder
抽象的生成器
csharp
interface AbstarctBuilder
{
AbstarctBuilder BuildDay(DateTime day);
AbstarctBuilder AddHotel(string hotel);
AbstarctBuilder AddReservation(string reservation);
AbstarctBuilder AddSpecialEvent(string specialEvent);
AbstarctBuilder AddTickets(string[] tickets);
string GetVacationPlanner();
}
VacationBuilder
具体的生成器
csharp
class VacationBuilder : AbstarctBuilder
{
List<Vacation> _vacations = new List<Vacation>();
Vacation _currentVacation;
public AbstarctBuilder BuildDay(DateTime day)
{
_currentVacation = new Vacation();
_vacations.Add(_currentVacation);
_currentVacation.Day = day;
return this;
}
public AbstarctBuilder AddHotel(string hotel)
{
_currentVacation.Hotels.Add(hotel);
return this;
}
public AbstarctBuilder AddReservation(string reservation)
{
_currentVacation.Reservations.Add(reservation);
return this;
}
public AbstarctBuilder AddSpecialEvent(string specialEvent)
{
_currentVacation.SpecialEvents.Add(specialEvent);
return this;
}
public AbstarctBuilder AddTickets(string[] tickets)
{
_currentVacation.Tickets.AddRange(tickets);
return this;
}
public string GetVacationPlanner()
{
return JsonConvert.SerializeObject(_vacations);
}
}
Client
客户端测试代码
csharp
AbstarctBuilder builder = new VacationBuilder();
builder.BuildDay(new DateTime(2020, 1, 1))
.AddHotel("葛雷巴旅馆")
.AddReservation("棒球比赛")
.AddSpecialEvent("拨打接听付费电话")
.AddTickets(new string[] { "《美丽人生》电影票", "张学友演唱会票" });
builder.BuildDay(new DateTime(2020, 1, 2))
.AddHotel("葛雷巴旅馆")
.AddReservation("棒球比赛决赛")
.AddSpecialEvent("继续拨打接听付费电话");
Console.WriteLine(builder.GetVacationPlanner());