3

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

这是我正在尝试做的一个简单示例:

我有一个带有 getter 的类,用于 int 和其他一些使用 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 的调用。

有没有办法可以修改我对装饰器模式的使用以达到我想要的结果?或者我可以用来让它按我想要的方式工作的其他模式/解决方案?

谢谢

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

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

于 2013-08-20T09:21:23.383 回答
0

你的错误很明显。当您调用MyDecorator.complexStuff()is delegate 时,此调用直接委托给MyClass decorated委托,其中getValue()方法未被覆盖,因为它在MyDecoratorwhich is not中被覆盖MyClass。换句话说,MyDecorator HAS-A MyClass,但NOT IS-A 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 回答