専用インターフェースは、ドメイン固有のタイプ階層でオプション機能を公開するための良い方法のようです。ただし、これらはデコレータおよび複合パターンの使用を妨げます。これは、この種の階層でも一般的です。
特に、おそらくこれらのインターフェイスの可能な組み合わせごとにデコレータ/コンポジットを実装する必要はないので、多くの場合、すべてのオプションのインターフェイスを実装し、タイプチェックを使用して呼び出しを選択的に転送します。これにより、インターフェイスを分離する目的が損なわれます。
Javaコレクションフレームワークが使用する別の方法は、すべての操作を基本型に含め、それらをダミー実装で埋めるだけです。Java 8のデフォルトメソッドこの使用法をさらに容易にします。
ある意味で、これはデータベースの世界でのnull許容列の議論のように感じられます。より実用的な後者のアプローチに対して強い議論はありますか?
私が過去に使用したこの問題の1つの解決策(多数のデコレーターが比較的単純なベースに多数の可能なインターフェースを追加する場合)に関係なく、デコレーターとそれらがラップするクラスの両方に基本クラスを用意することです彼らが実装するインターフェースで、メソッドが宣言されています(Javaの構文を使用)。
public <T> T findImplementation (Class<T> cls) {
if (cls.isAssignableFrom(getClass())
return cls.cast(this);
return wrapped.findImplementation (cls);
}
デコレータ以外の実装は、リクエストを渡す場所がないため、リクエストを渡すのではなくnullを返すことは明らかです。
代替の課題は、オプション機能の追加/変更/削除がより困難になることです。たとえば、新しいオプション機能を追加する場合は、基本クラスを変更してから、すべてのサブクラスを変更して、機能または非機能を追加する必要があります。 no-opなどの適切なデフォルトがある場合、これは多少軽減できるため、機能をサポートするサブタイプのみが必要な部分をオーバーライドする必要があります。これらのオプション機能が少なく、比較的安定していて、変更される可能性が低い場合は、スーパータイプに追加するだけで十分です。そうでない場合、メンテナンスが手に負えなくなる可能性があります。
スーパータイプからタイプを回復するための最も一般的な設計パターンは ビジターパターン です。単一のオブジェクトが複数のインターフェースを実装する可能性があるため、これは状況によってはトリッキーになる可能性がありますが、いくつかの変更を加えても実行できる場合があります。