我遇到以下情况:
我的Analyzer
类型大致如下
interface Analyzer {
int computeValue();
String performAnalysis();
}
通过类似
的方式实现class AnalyzerImpl implements Analyzer {
@Override
public int computeValue() {
return 5;
}
@Override
public String performAnalysis() {
return "Result: " + computeValue();
}
}
(在我的实际代码中,performAnalysis
使用几种不同复杂度的computeValue
方法执行许多计算。)
现在我需要在运行时有选择地调整Analyzer
对象的行为(或者使用调整行为创建一个包装器)。
我添加了调整方法:
public Analyzer tweakAnalyzer(Analyzer untweakedAnalyzer) { ... }
并尝试使用decorator pattern:
解决它class AnalyzerDecorator implements Analyzer {
Analyzer delegate;
public AnalyzerDecorator(Analyzer delegate) {
this.delegate = delegate;
}
@Override
public int computeValue() {
return delegate.computeValue();
}
@Override
public String performAnalysis() {
return delegate.performAnalysis();
}
}
然后我按如下方式实施tweakAnalyzer
:
public Analyzer tweakAnalyzer(Analyzer untweakedAnalyzer) {
return new AnalyzerDecorator(untweakedAnalyzer) {
@Override
public int computeValue() {
return 1337; // tweaked value!
}
};
}
然而,在做的时候
tweakAnalyzer(new AnalyzerImpl()).performAnalysis();
我根据需要获得了未被识别的值 Result: 5
,而不是Result: 1337
。
(这是因为调整后的分析器与未经过分析的分析器不是同一个对象,它只是一个包装器,因此computeValue
中对AnalyzerImpl
的调用不能按预期工作。)
我想在运行时调整对象的行为。我使用了装饰器模式,但“丢失”了所有虚拟方法。
解决这个问题的最佳方法是什么,即我应该如何以某种方式调整Analyzer
的行为,以便我不会松开虚拟方法查找或者无关紧要如果我这样做?
答案 0 :(得分:5)
问题是你的装饰师没有被performAnalysis
调用,因为它不知道你装饰了这个类。
您应该将performAnalysis
和computeValue
分为两类(Analyzer
performAnalysis
和Calculator
computeValue
这样,您可以单独装饰它们,并将装饰好的计算器传递到Analyzer
a'la performAnalysis(Calculator calculator)
。
示例at IDEOne。是的,它基本上是行动中的Strategy Pattern。
答案 1 :(得分:1)
您是否可以访问分析器对象的代码?如果是这样,您可以使用策略模式将其设计为可调整。
替代方案(具有多次调度种类的模板模式):
abstract class Analyzer {
public final int ComputeValue () {
return doComputeValue (this);
}
public final string PerformAnalysis () {
return doPerformAnalysis (this);
}
protected abstract int doComputeValue (Analyzer myself);
protected abstract string doPerformAnalysis (Analyzer myself);
}
class AnalyzerImpl extends Analyzer {
protected int doComputeValue (Analyzer myself) {
...
}
protected string doPerformAnalysis (Analyzer myself) {
return "Result: " + myself.ComputeValue();
}
}
class AnalyzerDecorator extends Analyzer {
Analyzer delegate;
...
protected string doPerformAnalysis (Analyzer myself) {
return delegate.doPerformAnalysis (myself);
}
protected int doComputeValue (Analyzer myself) {
return delegate.doComputeValue (myself);
}
}