我刚刚遇到了一个我以前见过的模式,并想得到关于它的意见。有问题的代码涉及这样的接口:
public interface MyCrazyAnalyzer {
public void setOptions(AnalyzerOptions options);
public void setText(String text);
public void initialize();
public int getOccurances(String query);
}
预期的用法是这样的:
MyCrazyAnalyzer crazy = AnalyzerFactory.getAnalyzer();
crazy.setOptions(true);
crazy.initialize();
Map<String, Integer> results = new HashMap<String, Integer>();
for(String item : items) {
crazy.setText(item);
results.put(item, crazy.getOccurances);
}
其中有一些原因。setText(...) 和 getOccurances(...) 之所以存在,是因为在对数据进行相同的昂贵分析之后,您可能想要执行多个查询,但这可以重构为结果类。
为什么我认为这很糟糕:实现以接口未明确指示的方式存储状态。我还看到过类似的事情,涉及需要调用“prepareResult”,然后是“getResult”的接口。现在,我可以想到使用其中一些功能的精心设计的代码。Hadoop Mapper 接口扩展了 JobConfigurable 和 Closeable,但我看到了很大的不同,因为它是一个使用用户代码实现这些接口的框架,而不是一个可以有多个实现的服务。我认为与包含必须调用的“关闭”方法相关的任何事情都是合理的,因为没有任何其他合理的方法可以做到这一点。在某些情况下,例如 JDBC,这是抽象泄漏的结果,但在我想到的两段代码中,它
我的问题是:
- 每个人都同意这是一个设计不佳的界面吗?
- 这是描述的反模式吗?
- 这种初始化是否属于接口?
- 这对我来说似乎是错误的,因为我偏爱函数式风格和不变性吗?
如果这很常见以至于值得命名,我建议对接口使用“秘密握手”反模式,当接口本身不是有状态的(如集合)时,它会强制您以特定顺序调用多个方法。