4

背景

我处于以下情况:

我有一个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) { ... }

并尝试使用装饰器模式解决它:

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预期的值。

(这是因为经过调整的分析器与未调整的分析器不是同一个对象,它只是一个包装器,因此对computeValuein的调用AnalyzerImpl无法按预期工作。)

完整的 ideone.com 示例。

TL;博士:

我想在运行时调整对象的行为。我使用了装饰器模式,但“丢失”了所有虚拟方法。

问题:

解决此问题的最佳方法是什么,即我应该如何调整 an 的行为,以Analyzer使我不会丢失虚拟方法查找,或者如果我这样做也没关系?

4

2 回答 2

5

问题是你的装饰器没有被调用,performAnalysis因为它不知道你装饰了这个类。

您可能应该分成两个类(withperformAnalysis和with )computeValueAnalyzerperformAnalysisCalculatorcomputeValue

这样,您可以独立装饰它们,并将装饰的计算器传递给Analyzera'la performAnalysis(Calculator calculator)

IDEOne的一个例子。是的,它基本上是行动中的战略模式

于 2012-08-26T07:57:25.203 回答
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);
    }
}
于 2012-08-26T08:05:10.450 回答