-5

女士们先生们。

我正在阅读Google 的 Closure Templates 文档。

那里没有那么多代码,但它代表了我难以理解的内容(特别是在 Java 中)。我将逐行进行:

// Bundle the Soy files for your project into a SoyFileSet.
SoyFileSet sfs = new SoyFileSet.Builder().add(new File("simple.soy")).build();

我明白了。收集多个模板文件的对象。美好的。但为什么.Builder()?为什么不只是new SoyFileSet().add(...).build()

// Compile the template into a SoyTofu object.
// SoyTofu's newRenderer method returns an object that can render any template in file set.
SoyTofu tofu = sfs.compileToJavaObj();

美好的。但我为什么要这个?收集完文件后,我期待的只是sfs.render(Map<> data). 为什么我需要将其编译为 Java 对象?

最后...

// Call the template with no data.
System.out.println(tofu.newRenderer("examples.simple.helloWorld").render());

太好了,为什么我必须创建一个中间对象才能调用它的方法?为什么sfs对象不能有.render()方法?为什么我需要一个Renderer对象?

Java 令人沮丧,为什么事情不以直截了当的方式完成?

4

2 回答 2

6
  1. SoyFileset可能是一个不可变对象,因此您可以使用 aBuilder一步构建它。顺便说一句,您的“为什么不”反例没有多大意义,因为它也以build. 在您的情况下build,不需要。

  2. SoyTofu是一个重量级的工厂对象,需要花费时间和空间来生产。您想多次重复使用它来生成渲染器。这就是为什么您在单独的步骤中创建它,然后保留它的原因。

  3. 您需要一个newRenderer,因为渲染是一个复杂的过程,涉及相当多的内部状态。对象的Renderer实例变量是当程序流通过其方法时保持状态的地方。您可能还会在渲染器上获得一些生命周期/状态方法,可能是为了查看渲染是如何进行的,或者在渲染之前提供一些额外的信息/配置。

这是经典模式的一个示例,我们将工作划分为预先构建的重型、不可变、线程安全、长寿命的工厂对象和轻量级、非线程安全、可变、一次性的对象,它们共享不可变的状态他们的工厂在一个线程中完成一项任务,然后被丢弃。

总而言之:这些都是设计精良、行业实力强大的 API 的标志。Java 不一定看起来像那样,但是如果您采用直接的方法,那么您会在性能方面给自己开枪,甚至内存不足。

于 2012-07-12T11:51:33.280 回答
6

Builder和类似名称的Factory方法被用作工厂设计模式的一部分。当由于某种原因需要集中创建对象时,这很有用。例如,工厂可能出于效率原因在内部保留一个对象池,而不是每次都返回一个新实例。

于 2012-07-12T11:57:28.647 回答