我有一个TemplateEngine
接口,其实现方式为MoustacheTemplateEngine
,FreemarkerTemplateEngine
等。
public interface TemplateEngine<T> {
public T compileTemplate(String templateStr);
public void merge(T t, Map<String, Object> data);
public String getTemplateLang();
}
compileTemplate
方法的目的是启用已编译模板的缓存。
这是一个实现示例:
import com.github.mustachejava.Mustache;
public class MoustacheTemplateEngine implements TemplateEngine<Mustache> {
@Override
public Mustache compileTemplate(String templateStr) {
// return compiled template;
}
@Override
public void merge(Mustache compiledTemplate, Map<String, Object> data) {
// merge
}
@Override
public String getTemplateLang() {
return "moustache";
}
}
我希望根据提供的模板语言创建一个返回TemplateEngine
的工厂。 工厂和使用工厂的客户对TemplateEngine
实施一无所知。
public class TemplateEngineFactory {
private Map<String, TemplateEngine<?>> TEMPLATE_ENGINE_REGISTRY = new HashMap<>();
@PostConstruct
public void init() {
// Scan all TemplateEngine impls in classpath and populate registry
}
public TemplateEngine<?> getTemplateEngine(String templateLang) {
return TEMPLATE_ENGINE_REGISTRY.get(templateLang);
}
}
客户将按以下方式使用工厂。
Map<String, Object> data = new HashMap<>();
data.put("name", "Tom");
TemplateEngine<?> templateEngine = factory.getTemplateEngine("moustache");
Object compiledTemplate = templateEngine.compileTemplate("Hi {{name}}");
templaeEngine.merge(compiledTemplate, data); // compile error
错误为The method merge(capture#3-of ?, Map<String,Object>) in the type TemplateEngine<capture#3-of ?> is not applicable for the arguments (Object, Map<String,Object>)
。
我理解错误,并且我知道我的API设计因工厂中使用通配符而存在缺陷。我的问题是如何为这种用例设计工厂并避免不安全的演员?
答案 0 :(得分:0)
您需要在某些时候进行不安全的演员表。最好的选择是,
public <T> TemplateEngine<T> getTemplateEngine(String templateLang) {
return (TemplateEngine<T>) TEMPLATE_ENGINE_REGISTRY.get(templateLang);
}
然后你可以称之为,
TemplateEngine<Mustache> templateEngine = factory.getTemplateEngine("moustache");
答案 1 :(得分:-1)
只需删除通配符,将其替换为:
TemplateEngine<?> templateEngine = factory.getTemplateEngine("moustache");
到此:
TemplateEngine templateEngine = factory.getTemplateEngine("moustache");
。
当您致电工厂获取所需的TemplateEngine
时,您不需要显示通配符。