首先,我想承认这个问题与this other one 非常相似。 ,但我想问得更具体,并希望获得更高质量的答案。
最近我学习了一个教程,其中使用 Director 实现了 Builder 模式。为了演示目的,我简化了类:
public class Director
{
private readonly Builder _builder;
public Director(Builder builder)
{
_builder = builder;
}
public void BuildProduct()
{
_builder.CreateProduct();
_builder.BuildPart1();
_builder.BuildPart2();
}
public Product GetProduct() => _builder.GetProduct();
}
public abstract class Builder
{
protected Product Product;
internal void CreateProduct()
{
Product = new Product();
}
internal Product GetProduct() => Product;
internal abstract void BuildPart1();
internal abstract void BuildPart2();
}
public class Thing1Builder : Builder
{
internal override void BuildPart1() => Product.ThingStrings.Add("Thing-1 String-1");
internal override void BuildPart2() => Product.ThingStrings.Add("Thing-1 String-2");
}
public class Thing2Builder : Builder
{
internal override void BuildPart1() => Product.ThingStrings.Add("Thing-2 String-1");
internal override void BuildPart2() => Product.ThingStrings.Add("Thing-2 String-2");
}
public class Product
{
internal readonly ICollection<string> ThingStrings = new List<string>();
public void Display()
{
foreach (string thingString in ThingStrings)
{
Console.WriteLine($"Thing string = {thingString}");
}
}
}
在学习教程的过程中,我不禁想知道为什么我们不直接将 Director 唯一有意义的方法(BuildProduct 方法)放入构建器的抽象基类中。这仍然确保所有混凝土构建器获得相同的构建模板,并消除看似无用的层。 Director带来了哪些优势?
这里我编写了几乎相同的代码,只是没有 director(省略了 Product 类,因为它没有改变):
public abstract class BuilderWithoutDirector
{
protected Product Product;
public void CreateProduct()
{
Product = new Product();
BuildPart1();
BuildPart2();
}
public Product GetProduct() => Product;
protected abstract void BuildPart1();
protected abstract void BuildPart2();
}
public class Thing1BuilderWithoutDirector : BuilderWithoutDirector
{
protected override void BuildPart1() => Product.ThingStrings.Add("Thing-1 String-1");
protected override void BuildPart2() => Product.ThingStrings.Add("Thing-1 String-2");
}
public class Thing2BuilderWithoutDirector : BuilderWithoutDirector
{
protected override void BuildPart1() => Product.ThingStrings.Add("Thing-2 String-1");
protected override void BuildPart2() => Product.ThingStrings.Add("Thing-2 String-2");
}
这两个示例的用法如下所示:
private static void UseWithDirector()
{
var director = new Director(new Thing1Builder());
director.BuildProduct();
var thing1 = director.GetProduct();
director = new Director(new Thing2Builder());
director.BuildProduct();
var thing2 = director.GetProduct();
thing1.Display();
thing2.Display();
}
private static void UseWithoutDirector()
{
var builder1 = new Thing1BuilderWithoutDirector();
builder1.CreateProduct();
var thing1 = builder1.GetProduct();
var builder2 = new Thing2BuilderWithoutDirector();
builder2.CreateProduct();
var thing2 = builder2.GetProduct();
thing1.Display();
thing2.Display();
}
这两种方法输出相同的东西。我看到了 Director 版本的一个优势提示,因为您创建了一个 director 并将其与多个构建器一起重用,它有一种顶级对象的感觉,知道发生了什么(请原谅那里的模糊逻辑),但您仍然必须了解并创建两个不同的构建器,那么为什么不直接使用它们呢?
将 Director
的工作放到 Builder
中违反了单一职责原则,因为 Builder
将有两个职责:
- 构建者的职责:知道如何实现
BuildPart1
和 BuildPart2
方法。
- Director 的职责:知道应该使用哪些部分哪个订单。
事实上,例如,当您更改基类 Builder
中对 BuildPart1
和 BuildPart2
的调用顺序时,所有您的具体 Thing*Builder
(s) 受到不必要的影响(它们必须重新编译和重新部署)。
我是一名优秀的程序员,十分优秀!