The decorator pattern loses the search for the virtual method. Any good alternatives or workarounds?

Background

I am in the following situation:

I have an Analyzer type that looks something like this

 interface Analyzer { int computeValue(); String performAnalysis(); } 

implemented by something like

 class AnalyzerImpl implements Analyzer { @Override public int computeValue() { return 5; } @Override public String performAnalysis() { return "Result: " + computeValue(); } } 

(In my actual code, performAnalysis does a lot of calculations using several different computeValue methods for various complexities.)

Now I need to selectively customize the behavior of the Analyzer object at runtime (or create a wrapper with modified behavior).

What I tried:

I added a setup method:

 public Analyzer tweakAnalyzer(Analyzer untweakedAnalyzer) { ... } 

and tried to solve it using a decorator drawing :

 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(); } } 

Then I implemented tweakAnalyzer as follows:

 public Analyzer tweakAnalyzer(Analyzer untweakedAnalyzer) { return new AnalyzerDecorator(untweakedAnalyzer) { @Override public int computeValue() { return 1337; // tweaked value! } }; } 

However, when executed

 tweakAnalyzer(new AnalyzerImpl()).performAnalysis(); 

I get an unexpressed Result: 5 value, not Result: 1337 as desired.

(This is due to the fact that the modified analyzer is not the same object as the fuzzy analyzer, but just a shell, so the call to computeValue in AnalyzerImpl does not work as intended.)

A complete example of ideone.com.

TL DR:

I want to customize the behavior of an object at runtime. I used the decorator pattern, but β€œlost” all the virtual methods.

Question:

What is the best way to solve this problem, that is, how can I configure the behavior of the Analyzer so that I either do not lose the search in the virtual method, or it does not matter if I do?

+4
source share
2 answers

The problem is that your decorator is not called by performAnalysis , since it does not know that you decorated the class.

You should performAnalysis split performAnalysis and computeValue into two classes ( Analyzer with performAnalysis and Calculator with computeValue )

Thus, you can decorate them yourself and transfer the decorated calculator to Analyzer a'la performAnalysis(Calculator calculator) .

Example in IDEOne . And yes, this is basically a Strategy Pattern in action.

+5
source

Do you have access to the analyzer object code? If so, you can configure it for customization using the strategy template.

Alternative (template template with several types of sending):

 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); } } 
+1
source

All Articles