使用构建器模式的一些常见的、真实的例子是什么?它能给你买什么?为什么不直接使用工厂模式?


当前回答

. net StringBuilder类是构建器模式的一个很好的例子。它主要用于在一系列步骤中创建字符串。执行ToString()的最终结果始终是一个字符串,但该字符串的创建取决于使用StringBuilder类中的哪些函数。总而言之,基本思想是构建复杂的对象,并隐藏如何构建对象的实现细节。

其他回答

当我想在Java中为XML使用标准XMLGregorianCalendar来对DateTime进行对象封送时,我听到了很多关于使用它是多么沉重和麻烦的评论。我试图控制xs:datetime结构中的XML字段来管理时区,毫秒等。

因此,我设计了一个实用程序,从GregorianCalendar或java.util.Date构建一个xml公历。

由于我工作的地方,我不允许在网上分享它,但这里有一个客户如何使用它的例子。它抽象了XMLGregorianCalendar的细节,并过滤了xs:datetime中较少使用的一些实现。

XMLGregorianCalendarBuilder builder = XMLGregorianCalendarBuilder.newInstance(jdkDate);
XMLGregorianCalendar xmlCalendar = builder.excludeMillis().excludeOffset().build();

假定此模式更像是一个过滤器,因为它将xmlCalendar中的字段设置为未定义,因此将它们排除在外,但它仍然“构建”它。我已经很容易地向构建器添加了其他选项,以创建xs:date和xs:time结构,并在需要时操作时区偏移量。

如果您曾经见过创建和使用XMLGregorianCalendar的代码,您就会看到这是如何使它更容易操作的。

当你有很多选择要处理的时候,你就用它。想想jmock这样的东西:

m.expects(once())
    .method("testMethod")
    .with(eq(1), eq(2))
    .returns("someResponse");

这感觉更自然,而且是可能的。

还有xml构建,字符串构建和其他很多东西。想象一下,如果java.util.Map将put作为构建器。你可以这样做:

Map<String, Integer> m = new HashMap<String, Integer>()
    .put("a", 1)
    .put("b", 2)
    .put("c", 3);

构建器和工厂之间的关键区别是,当你需要做很多事情来构建一个对象时,构建器是有用的。例如,想象一个DOM。您必须创建大量节点和属性才能获得最终对象。当工厂可以在一个方法调用中轻松创建整个对象时,就使用工厂。

使用构建器的一个例子是构建一个XML文档,我在构建HTML片段时使用了这个模型,例如,我可能有一个构建器来构建一个特定类型的表,它可能有以下方法(参数未显示):

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

然后这个构建器会为我输出HTML。这比遍历一个大型过程方法容易得多。

在维基百科上查看生成器模式。

以餐厅为例。“今天的饭菜”的创建是一种工厂模式,因为您告诉厨房“给我今天的饭菜”,然后厨房(工厂)根据隐藏的标准决定生成什么对象。

如果你订购了一个定制的披萨,建造者就会出现。在这种情况下,服务员告诉厨师(建筑工人)“我需要一个披萨;加奶酪、洋葱和培根!”因此,构建器公开了生成的对象应该具有的属性,但隐藏了如何设置这些属性。

在浏览微软MVC框架时,我对构建器模式有了一些想法。我在ControllerBuilder类中遇到了这种模式。这个类返回控制器工厂类,然后用它来构建具体的控制器。

我认为使用构建器模式的优点是,您可以创建自己的工厂并将其插入到框架中。

@Tetha,可以有一家意大利人开的餐厅(框架),供应披萨。为了准备披萨,Italian guy (Object Builder)使用Owen (Factory)和一个披萨基(基类)。

现在印度人从意大利人手里接管了餐厅。印度餐厅(框架)提供dosa而不是披萨。为了准备dosa, Indian guy(对象构建器)使用fried Pan(工厂)和Maida(基类)

如果你看场景,食物是不同的,食物的制作方式是不同的,但在同一家餐厅(在同一框架下)。餐馆应该以这样一种方式建造,它可以支持中国菜、墨西哥菜或任何菜。框架内的对象构建器有助于你想要的插件料理。例如

class RestaurantObjectBuilder
{
   IFactory _factory = new DefaultFoodFactory();

   //This can be used when you want to plugin the 
   public void SetFoodFactory(IFactory customFactory)
   {
        _factory = customFactory;
   }

   public IFactory GetFoodFactory()
   {
      return _factory;
   }
}