旧游无处不堪寻
无寻处,惟有少年心
设计模式-生成器

生成器模式(Builder Pattern)是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

解释


生成器模式建议将对象构造代码从产品类中抽取出来,并将其放在一个名为生成器的独立对象中。

该模式会将对象构造过程划分为一组步骤。每次创建对象时,你都需要通过生成器对象执行一系列步骤。重点在于你无需调用所有步骤,而只需调用创建特定对象配置所需的那些步骤即可。

当你需要创建不同形式的产品时,其中的一些构造步骤可能需要不同的实现。在这种情况下,你可以创建多个不同的生成器,用不同方式实现一组相同的创建步骤。然后你就可以在创建过程中使用这些生成器(例如按顺序调用多个构造步骤)来生成不同类型的对象。

你可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类。主管类可定义创建步骤的执行顺序,而生成器则提供这些步骤的实现。
严格来说,你的程序中并不一定需要主管类。客户端代码可直接以特定顺序调用创建步骤。不过,主管类中非常适合放入各种例行构造流程,以便在程序中反复使用。

生成器模式 UML


适用场景


  1. 使用生成器模式可避免重叠构造函数的出现。生成器模式让你可以分步骤生成对象,而且允许你仅使用必须的步骤。应用该模式后,你再也不需要将几十个参数塞进构造函数里了
  2. 当你希望使用代码创建不同形式的产品,可使用生成器模式
  3. 使用生成器构造组合树或其他复杂对象

代码示例


using System;
namespace BuilderPatternDemo
{
// builder
public interface IBuilder
{
void BuildPartA();
void BuildPartB();
void BuildPartC();
}

public class ConcreteBuilder : IBuilder
{
private Product _product = new Product();

public ConcreteBuilder()
{
Reset();
}

public void Reset()
{
_product = new Product();
}

public void BuildPartA()
{
_product.Add("PartA1");
}

public void BuildPartB()
{
_product.Add("PartB1");
}

public void BuildPartC()
{
_product.Add("PartC1");
}

public Product GetProduct()
{
Product result = _product;
Reset();
return result;
}
}

// product
public class Product
{
private List _parts = new List();

public void Add(string part)
{
_parts.Add(part);
}

public string ListParts()
{
string str = string.Empty;
for (int i = 0; i < _parts.Count; i++)
{
str += _parts[i] + ", ";
}
str = str.Remove(str.Length - 2);

return "Product parts: " + str + "\n";
}
}

// director
public class Director
{
private IBuilder _builder;

public IBuilder Builder
{
set { _builder = value; }
}

public void BuildMinimalViableProduct()
{
_builder.BuildPartA();
}

public void BuildFullFeaturedProduct()
{
_builder.BuildPartA();
_builder.BuildPartB();
_builder.BuildPartC();
}
}

// program
class Program { static void Main(string[] args)
{
var director = new Director();
var builder = new ConcreteBuilder();
director.Builder = builder;

Console.WriteLine("Standard basic product:");
director.BuildMinimalViableProduct();
Console.WriteLine(builder.GetProduct().ListParts());
Console.WriteLine("Standard full featured product:");
director.BuildFullFeaturedProduct();
Console.WriteLine(builder.GetProduct().ListParts());

Console.WriteLine("Custom product:");
builder.BuildPartA();
builder.BuildPartC();
Console.Write(builder.GetProduct().ListParts());
// output

// Standard basic product:
// Product parts: PartA1
// Standard full featured product:
// Product parts: PartA1, PartB1, PartC1
// Custom product:
// Product parts: PartA1, PartC1
}
}