使用生成器模式来解决问题
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
生成器模式的结构和说明
- Builder:生成器接口,定义创建一个 Product 对象所需的各个部件的操作。
- ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装 Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。
- Director:指导者,也被称为导向者,主要用来使用 Builder 接口,以一个统一的过程来构建所需要的 Product 对象。
- Product:产品,表示被生成器构建的复杂对象,包含多个部件。
示例代码
namespace NetCore3Console.Builder
{
/// <summary>
/// 生成器接口,定义创建一个产品对象所需的各个部件的操作
/// </summary>
public interface IBuilder
{
/// <summary>
/// 示意方法,构建某个部件
/// </summary>
void BuildPart();
}
/// <summary>
/// 具体的生成器实现对象
/// </summary>
public class ConcreteBuilder : IBuilder
{
private IProduct resultProduct;
public IProduct GetResult()
{
return resultProduct;
}
public void BuildPart()
{
//构建某个部件的功能处理
}
}
/// <summary>
/// 被构建的产品对象的接口
/// </summary>
public interface IProduct
{
//定义产品的操作
}
/// <summary>
/// 指导者,指导使用生成器的接口来构建产品的对象
/// </summary>
public class Director
{
//持有当前需要使用的生成器对象
private IBuilder _builder;
//构造方法,传入生成器对象
public Director(IBuilder builder)
{
_builder = builder;
}
//示意方法,指导生成器构建最终的产品对象
public void Construct()
{
//通过使用生成器接口来构建最终的产品对象
_builder.BuildPart();
}
}
}
认识生成器模式
生成式功能
生成器模式的主要功能是构建复杂的产品,而且是细化的、分步骤的构建产品,也就是生成器模式重在一步一步解决构造复杂对象的问题。
更为重要的是,这个构建的过程是统一的、固定不变的,变化的部分放到生成器部分了,只要配置不同的生成器,那么同样的构建过程,就能构建出不同的产品来。
生成器模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。具体的构造实现可以很方便地扩展和切换,从而可以灵活地组合来构造出不同的产品对象。
生成式的构成
- 一个部分是 Builder 接口,这里是定义了如何构建各个部件,也就是知道每个部件功能如何实现,以及如何装配这些部件到产品中去;
- 另外一个部分是 Director,Director 是知道如何组合来构建产品,也就是说 Director负责整体的构建算法,而且通常是分步骤地来执行。
不管如何变化,Builder 模式都存在这么两个部分一个部分是部件构造和产品装配另一个部分是整体构建的算法。
生成器模式的使用
应用生成器模式的时候,可以让客户端创造 Director,在 Director 里面封装整体构建算法,然后让 Director 去调用 Builder,让 Builder 来封装具体部件的构建功能,这就如同前面的例子。
使用生成器构建复杂对象
要想简洁直观、安全性好,又具有很好的扩展性地来创建这个对象的话,一个较好的选择就是使用 Builder 模式,把复杂的创建过程通过 Builder 来实现。
采用 Builder 模式来构建复杂的对象,通常会对 Builder 模式进行一定的简化,因为目标明确,就是创建某个复杂对象,因此做适当简化会使程序更简洁。大致简化如下:
- 由于是用 Builder 模式来创建某个对象,因此就没有必要再定义一个 Builder 接口,直接提供一个具体的构建器类就可以了。
- 对于创建一个复杂的对象,可能会有很多种不同的选择和步骤,干脆去掉“指导者”,把指导者的功能和 Client 的功能合并起来,也就是说,Client 这个时候就相当于指导者,它来指导构建器类去构建需要的复杂对象。
namespace NetCore3Console.Builder1
{
/// <summary>
/// 保险合同的对象
/// </summary>
public class InsuranceContract
{
//保险合同编号
private string contractId;
//被保险人的名称
private string personName;
//宝箱公司名称
private string companyName;
//保险开始生效日期
private long beginDate;
//失效日期
private long endDate;
//示例:其他数据
private string otherData;
public InsuranceContract(ConcreteBuilder builder)
{
contractId = builder.ContractId;
personName = builder.PersonName;
companyName = builder.CompanyName;
beginDate = builder.BeginDate;
endDate = builder.EndDate;
otherData = builder.OtherData;
}
/// <summary>
/// 示意:保险合同的某些操作
/// </summary>
public void SomeOperation()
{
//一些基础操作
}
}
/// <summary>
/// 构造保险合同对象的构建器
/// </summary>
public class ConcreteBuilder
{
public string ContractId { get; }
public string PersonName { get; set; }
public string CompanyName { get; set; }
public long BeginDate { get; }
public long EndDate { get; }
public string OtherData { get; set; }
/// <summary>
/// 构造方法,传入必须要有的参数
/// </summary>
/// <param name="contractId"></param>
/// <param name="beginDate"></param>
/// <param name="endDate"></param>
public ConcreteBuilder(string contractId,long beginDate,long endDate)
{
ContractId = contractId;
BeginDate = beginDate;
EndDate = endDate;
}
/// <summary>
/// 选填数据,被保险人员的名称
/// </summary>
/// <param name="personName"></param>
/// <returns></returns>
public ConcreteBuilder SetPersonName(string personName)
{
PersonName = personName;
return this;
}
public ConcreteBuilder SetCompanyName(string companyName)
{
CompanyName = companyName;
return this;
}
public ConcreteBuilder SetOtherData(string otherData)
{
OtherData = otherData;
return this;
}
/// <summary>
/// 构建方法
/// </summary>
/// <returns></returns>
public InsuranceContract Build()
{
return new InsuranceContract(this);
}
}
}
生成器模式的优点
- 松散耦合
生成器模式可以用同一个构建算法构建出表现上完全不同的产品,实现产品构建和产品表现上的分离。生成器模式正是把产品构建的过程独立出来,使它和具体产品的表现松散耦合,从而使得构建算法可以复用,而具体产品表现也可以灵活地、方便地扩展和切换。 - 可以很容易地改变产品的内部表示
在生成器模式中,由于Builder 对象只是提供接口给 Director 使用,那么具体的部件创建和装配方式是被 Builder 接口隐藏了的,Director 并不知道这些具体的实现细节。这样一来,要想改变产品的内部表示,只需要切换 Builder 的具体实现即可,不用管 Director,因此变得很容易。 - 更好的复用性
生成器模式很好地实现了构建算法和具体产品实现的分离。这样一来,使得构建产品的算法可以复用。同样的道理,具体产品的实现也可以复用,同一个产品的实现,可以配合不同的构建算法使用。
思考生成器模式
生成器模式的本质:分离整体构建算法和部件构造。
生成器模式的重心还是在于分离整体构建算法和部件构造,而分步骤构建对象不过是整体构建算法的一个简单表现,或者说是一个附带产物。
何时选用生成器模式
- 如果创建对象的算法,应该独立于该对象的组成部分以及它们的装配方式时。
- 如果同一个构建过程有着不同的表示时。