以前に見たパターンに出くわしたので、それについて意見を求めたいと思いました。問題のコードには、次のようなインターフェースが含まれます。
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 を拡張しますが、これらのインターフェースを実装するユーザー コードを使用するフレームワークであるのに対し、複数の実装を持つ可能性のあるサービスであるため、大きな違いが見られます。呼び出す必要がある「close」メソッドを含めることに関連するものはすべて正当化されると思います。これを行うための合理的な方法は他にないからです。JDBC のように、これは漏れやすい抽象化の結果である場合もありますが、私が考えている 2 つのコードでは、
私の質問は次のとおりです。
- 誰もがこれが貧弱に設計されたインターフェースであることに同意しますか?
- これは記述されたアンチパターンですか?
- この種の初期化はインターフェイスに属しますか?
- 私は機能的なスタイルと不変性を好むので、これは私には間違っているように思えますか?
これが名前に値するほど一般的である場合は、インターフェイスが本質的にステートフルではない場合 (コレクションのように)、特定の順序で複数のメソッドを呼び出すことを強制するインターフェイスの「シークレット ハンドシェイク」アンチ パターンをお勧めします。