你能解释一下为什么Google Closure模板使用了这么多毫无意义的中间对象吗?

-5 java

女士们先生们.

我正在阅读Google的Closure模板文档.

那里没有那么多代码,但它代表了我无法理解的东西(特别是在Java中).我会一行一行:

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

我明白了 收集多个模板文件的对象.精细.但为什么.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();
Run Code Online (Sandbox Code Playgroud)

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

最后......

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

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

Java令人沮丧,为什么不以简单的方式完成任务?

Mar*_*nik 6

  1. SoyFileset可能是一个不可变对象,所以你用Builder一个步骤来构建它.顺便说一下你的"为什么不"反例并没有多大意义,因为它也以此结束build.在您的情况下,build不需要.

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

  3. 你需要一个newRenderer因为渲染是一个复杂的过程,涉及相当多的内部状态.该Renderer对象的实例变量是当该国被保留作为程序流蜿蜒流过它的方法.您还可能在渲染器上获得一些生命周期/状态方法,可能是为了查看渲染的方式,或者可能在渲染之前提供一些额外的信息/配置.

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

总之:这些都是设计良好,行业优势的API的标志.Java并不必然像她那样,但是如果你去了直接的方法,你会搬起石头砸自己的脚的性能代价,甚至耗尽内存.


Tud*_*dor 6

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