问题(我可能滥用)装饰模式

时间:2013-08-20 08:30:11

标签: java decorator

我试图使用装饰器模式修改我的对象的行为但是遇到了一些障碍,装饰器模式似乎无法按照我想要的方式更改我的对象的功能。

以下是我想要做的一个简单示例:

我有一个带有getter的类和一些其他“复杂”的类,它使用getter进行一些计算

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。

有没有办法可以修改我对装饰器模式的使用来实现我想要的结果?或者我可以使用其他一些模式/解决方案来实现我的工作方式吗?

由于

3 个答案:

答案 0 :(得分: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。如果你愿意,装饰者类可以代替你。

答案 1 :(得分:0)

如果你不能修改MyClass,也许你可以从它派生并使用子类代替?然后,您可以覆盖getValue

答案 2 :(得分:0)

你的错误是显而易见的。当您致电MyDecorator.complexStuff()时,会直接将此来电委托给MyClass decorated委托,其中getValue()方法未被覆盖,因为MyDecorator中的MyClass覆盖了MyDecorator MyClass }。换句话说,MyClass HAS-A MyDecorator.complexStuff(),但不是IS-A 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(); } } 方法,但不能覆盖{{1}}方法:

{{1}}