問題のある (Java) クラス WindowItem があります。メソッドの 1 つがスレッドセーフではありません。WindowItem は外部フレームワークの一部であるため、修正できません。そこで、問題のメソッドに「同期」キーワードを持つデコレータを実装すると考えました。
Decorator は WindowItem を拡張し、WindowItem も含みます。Decorator パターンに従って、Decorator に含まれる WindowItem を呼び出すメソッドを Decorator に作成します。
ただし、WindowItem には、Decorator でオーバーライドできないいくつかの最終メソッドがあります。これにより、Decorator の透明性が損なわれます。これを明示的にしましょう:
public class WindowItem {
private List<WindowItem> windows;
public Properties getMethodWithProblem() {
...
}
public final int getwindowCount() {
return windows.size();
}
}
public class WindowItemDecorator extends WindowItem {
private WindowItem item;
public WindowItemDecorator(WindowItem item) {
this.item = item;
}
# Here I solve the problem by adding the synchronized keyword:
public synchronized Properties getgetMethodWithProblem() {
return super.getMethodWithProblem();
}
# Here I should override getWindowCount() but I can't because it's final
}
私自身のコードでは、どこかに WindowItem を渡す必要があるときはいつでも、最初にそれをデコレーターでラップしました: new WindowItemDecorator(item) -- そして、スレッド セーフの問題は消えます。ただし、私のコードが WindowItemDecorator で getwindowCount() を呼び出すと、常にゼロになります。「item」メンバーではなく、スーパークラスで getWindowCount() を実行します。
したがって、WindowItem の設計 (public final メソッドがあるという事実) により、このクラスの Decorator を作成することは不可能になっていると言えます。
それは正しいですか、それとも何か不足していますか?
この場合、ウィンドウのリストのコピーをデコレータに保持して同期を保つことができ、getWindowCount() の結果は正しいでしょう。しかし、その場合、私はフレームワークをフォークしてパッチを当てることを好みます...