设计模式:生成器

我已经找到了一个很好Builder模式示例(在C#中),但找不到一个,因为我不了解Builder模式,或者我正在尝试做一些从未想过的事情。 例如,如果我有一个抽象的汽车和抽象的构建方法来创建汽车零件,我应该能够将所有30个选择发送给Director,让它构建我需要的部件,然后构建我的汽车。 无论生产哪种汽车,卡车,半卡车等,我都应该能够以完全相同的方式“驾驶”它。

第一个问题是大多数示例硬编码属性值到具体部分,我认为应该来自数据库。 我认为这个想法是将我的选择发送给Director(来自数据源),并让构建器根据我的数据创建自定义产品。

第二个问题是我希望构建器方法实际创建部件然后将它们分配给产品,而不是传递字符串,而是真正的强类型产品部件。

例如,我想通过为我创建一个Builder制作表单字段来动态创建表单,包括标签,输入部分,validation等。这样我就可以从我的ORM中读取对象,查看对象的元数据,将其传递给我的Builder并将新创建的用户控件结果添加到我的Web表单中。

但是,我找到的每个Builder示例都只有硬编码数据,而不是将选择从主代码传递到Builder并开始定制产品。 一切似乎都是一个很大的静态案例陈述。 例如,如果我有三个参数,每个参数有10个选项,我不想构建30个具体的Builder方法,我想创建的只是足以制作我的产品所需的属性,可能只有三个。

我很想让Director只存在于主代码中。 应该有一种方法可以自动确定调用哪个具体的构建器方法,类似于多态和方法重载(尽管这是一个非常糟糕的例子),而不是在模式中使用case语句。 (每次我需要添加新的产品类型时,我都需要修改现有的Director,这很糟糕)。

我将在这里参考维基百科文章中的C#示例。

第一个问题是大多数示例硬编码属性值到具体部分,我认为应该来自数据库。 我认为这个想法是将我的选择发送给Director(来自数据源),并让构建器根据我的数据创建自定义产品。

在这种情况下,您将拥有实现PizzaBuilder的类,该类知道如何从数据库中检索数据。 你可以用几种方法做到这一点。

一个是做一个HawaiianPizzaBuilder。 当类初始化时,它会在数据库中查询Hawaiian Pizza并检索该行。 然后,当调用各种Build(x)方法时,它会将属性设置为检索到的数据库行的相应字段。

另一种方法就是制作一个PizzaDatabaseBuilder,并确保在初始化类时,您将传递给该类型披萨所需行的ID。 例如,而不是

waiter.PizzaBuilder = new HawaiianPizzaBuilder(); 

你用

 waiter.PizzaBuilder = new PizzaDatabaseBuilder("Hawaiian"); 

第二个问题是我希望构建器方法实际创建部件然后将它们分配给产品,而不是传递字符串,而是真正的强类型产品部件。

不应该是一个问题。 您需要的是另一个Factory / Builder类型模式来初始化Pizza的字段。 例如

代替

  public override void BuildDough() { pizza.Dough = "pan baked"; } 

你会做点什么的

  public override void BuildDough() { pizza.Dough = new DoughBuilder("pan baked"); } 

要么

  public override void BuildDough() { pizza.Dough = new PanBakedDoughBuilder(); } 

DoughBuilder可以转到数据库中的另一个表来正确填写PizzaDough类。

大多数情况下,BuilderPattern的调用如下所示:

 Car car = new CarBuilder().withDoors(4).withColor("red").withABS(true).build(); 

我从来没有想过这样,但LINQ(模式,而不是语法)实际上是一个建设者,对吧?

它是一个流畅的界面,可以构建查询,并可以在不同的表示forms中创建查询(SQL,内存中对象查询,Web服务查询,Bart de Smet甚至编写了L​​inq-to-Excel的实现)。

我会说你无法避免这些 – 你的零件几乎没有重载,并且在堆栈的某个地方有一个case / if语句。 在添加新课程时也必须修改代码可能是您唯一的选择。

话虽这么说,你可以得到其他一些模式的帮助 – 即工厂,可以帮助你在建设过程中。 同样合理地使用多态(例如,所有部分inheritance自某种类型,无论是类还是接口)都可以减少ifs / Cases和重载的数量。

希望这可以帮助。