论坛首页 Java企业应用论坛

FreeMarker在TemplateLoader的设计缺陷

浏览 5125 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-16  
在设计MeteorTL的TemplateLoader时,借鉴了下FreeMarker,
FreeMarker的TemplateLoader:
public interface TemplateLoader {

    public Object findTemplateSource(String name) throws IOException;

    public long getLastModified(Object templateSource);

    public Reader getReader(Object templateSource, String encoding) throws IOException;
    
    public void closeTemplateSource(Object templateSource) throws IOException;

}

初读此接口很费解,这是一个留给扩展者的SPI,但却让扩展者要看完那长篇的注释才能明白那个Object是干什么的。

TemplateLoader的第一目标是要通过模板name拿到Reader,
最初的想法肯定是:
public interface TemplateLoader {

    public Reader getReader(String name, String encoding) throws IOException;

}

但实现时,会发现Reader无法持有一些meta数据,如:用于热加载时比较是否更新用的lastModified时间等。

所以freemarker才会有上面的写法,用一个Object(大部分时候是File)传递,也就是 findTemplateSource(String name) 的返回值 Object templateSource 会被框架(接口调用者)通过参数回传给下面的三个函数。以至于此接口的契约依赖于框架的具体实现(即所有此接口的调用者,都应该遵守回传templateSource,而这些都是文档约束的)。

重构如下:
import java.io.IOException;

public interface TemplateLoader {
	
	public TemplateSource getTemplateSource(String name) throws IOException;

}


import java.io.IOException;
import java.io.Reader;

public interface TemplateSource {
	
	public static final long UNKOWN_TIME = -1;

	public long getLastModifiedTime();
	
	public Reader getReader(String encoding) throws IOException;
	
	public void close() throws IOException;
	
}


   发表时间:2007-06-27  
恩,有点像类的加载方式了。不过不是很理解为什么采用这种模型?
模版可以独立于上下文Context存在吗?如果不可以,那么模版的加载为什么采用这种模型?javatar兄是怎么考虑的?
0 请登录后投票
   发表时间:2007-06-29  
Template是可以独立于Context存在的。
Context相当于语言设计体系中的Runtime,
而Template是Compile期的产物,
Template不能包含任何动态数据,也不能持有可变的全局状态,必需保证线程安全,否则在多线程中,需要拷贝实例到ThreadLocal,这是很耗性能的。那运行期的数据状态怎么办呢,都交给Context管理,包括与外界的交互。

Template也是一种DSL语言,这种设计应该是合理的。
0 请登录后投票
   发表时间:2007-08-17  
我个人觉得TemplateSource设计成为抽象类更加好一些,因为它本身就是对Reader以及时间的一个封装嘛

import java.io.IOException;   
import java.io.Reader;   
  
public abstract class TemplateSource {   
       
    private Reader rd;
    
    private long lastModifiedTime;
	
    public static final long UNKOWN_TIME = -1;   
  
    public long getLastModifiedTime();   
       
    public Reader getReader(String encoding) throws IOException;   
       
    public void close(Reader reader) throws IOException;   
       
}   
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics