3

デコレータ パターンを使用してオブジェクトの動作を変更しようとしていますが、デコレータ パターンがオブジェクトの機能を希望どおりに変更できないように思われる問題が発生しました。

これが私がやろうとしていることの簡単な例です:

int のゲッターと、ゲッターを使用して計算を行うその他の「複合体」を持つクラスがあります。

public class MyClass implements MyInterface {
    private int value = 5;

    @Override
    public int getValue() {
        return value;
    }

    @Override
    public int complexStuff() {
        return 50 + getValue();
    }
}

インターフェイスによって定義されたすべての呼び出しを MyClass インスタンスに渡すだけの抽象デコレータがあります

public abstract class MyDecorator implements MyInterface {
    private MyClass decorated;

    public MyDecorator(MyClass decorated) {
        this.decorated = decorated;
    }

    @Override
    public int getValue() {
        return decorated.getValue();
    }

    @Override
    public int complexStuff() {
        return decorated.complexStuff();
    }
}

MyClassインスタンスを装飾して、影響を受けるgetValue()ような方法でメソッドの動作を変更できるようにしたいと考えていますcomplexStuff()

たとえば、次のように MyClass インスタンスを装飾するとします。

MyDecorator myDecorator = new MyDecorator(myClassInstance) {
    @Override
    public int getValue() {
        return 100;
    }
};

私が現在これを実装している方法では、 への呼び出しmyDecorator.getValue()は 100 を返しますが、 への呼び出しはインスタンスが装飾されていないmyDecorator.complexStuff()かのように 55 を返します。MyClass私が欲しいのは、への呼び出しがmyDecorator.complexStuff()150 を返すことです。

目的の結果を得るためにデコレータ パターンの使用を変更する方法はありますか? または、これを希望どおりに機能させるために使用できる他のパターン/ソリューションはありますか?

ありがとう

4

3 に答える 3

0

デコレータ パターンを使用してこの目標を達成できるとは思いません。既存のインスタンスの動作を変更しようとしていますが、これは簡単なことではありません (可能であれば)。

次のようなものが機能します。

public class MyClass implements MyInterface {
  private ValueProvider provider = new ValueProvider() {    
    @Override
    public int getValue() {
      return 5;
    }
  };

  // (You may wish to include this method in MyInterface)
  public void setValueProvider(ValueProvider provider) {
    this.provider = provider;
  }

  @Override
  public int getValue() {
      return provider.getValue();
  }

  @Override
  public int complexStuff() {
      return 50 + getValue();
  }
}

ValueProviderその後、実行時に別のものに置き換えることができます。必要に応じて、デコレータ クラスで代用できます。

于 2013-08-20T09:02:54.007 に答える
0

あなたの間違いは明らかです。を呼び出すMyDecorator.complexStuff()と、この呼び出しはデリゲートに直接デリゲートされますMyClass decoratedgetValue()メソッドはオーバーライドされMyDecoratorませんMyClass。つまり、IS- AではなくMyDecorator HAS- Aです。MyClass MyClass

問題を解決するには、MyDecorator.complexStuff()メソッドを変更するだけです。getValue()これを使用すると、メソッドを自由にオーバーライドできますが、メソッドはオーバーライドできませんcomplexStuff():

abstract class MyDecorator implements MyInterface {

    private final MyClass decorated;

    public MyDecorator(MyClass decorated) {
        this.decorated = decorated;
    }

    // this method is overridden, and returns 100 always
    @Override
    public int getValue() {
        return decorated.getValue();
    }

    @Override
    public final int complexStuff() {
        return decorated.complexStuff() - decorated.getValue() + getValue();
    }
}
于 2018-06-09T09:17:09.250 に答える