bub*_*ing 4 c# design-patterns builder
首先,我想承认这个问题与另一个问题非常相似,但我想问更具体的问题,并希望获得更高质量的答案。
最近,我学习了一个教程,其中使用 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}");
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我按照教程进行操作时,我忍不住想知道为什么我们不将 Director 唯一有意义的方法(BuildProduct 方法)放入构建器的抽象基类中。这仍然确保所有混凝土建筑商获得相同的建筑模板,并消除看似无用的层。导演有什么优势?
在这里,我编写了几乎相同的代码,只是没有导演(产品类被省略,因为它没有改变):
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");
}
Run Code Online (Sandbox Code Playgroud)
这两个例子的用法如下:
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();
}
Run Code Online (Sandbox Code Playgroud)
这两个方法输出相同的内容。我看到了Director版本的一个优点,即您创建一个director并与多个构建器重用它,这有一种知道正在发生什么的顶级对象的感觉(请原谅那里的模糊逻辑),但您仍然必须了解并创建两个不同的构建器,那么为什么不直接使用它们呢?
PuttingDirector
的工作Builder
违反了单一责任原则,因为遗嘱Builder
有两个责任:
BuildPart1
和BuildPart2
方法。事实上,例如,当您更改基类BuildPart1
和中的调用顺序时,所有具体的都会受到不必要的影响(它们必须重新编译和重新部署)。BuildPart2
Builder
Thing*Builder