dsollen
dsollen

Reputation: 6459

can java or eclipse easily 'auto wrap' class methods that aren't being changed when using decorator pattern

I've found a few times that I was considering the decorator pattern, and was tempted not to do it just because it could be so tedious to wrap a classes methods to pass the capability down to the class I was decorating. Writing:

 public int methodA(int argument){
     return decoratee.methodA(argument);
 }

over and over again for a dozen methods when I'm only really interested in modifying one or two of them is just tedious. Plus, if I add a new method to the class/interface I need to remember to go back and the method in to all the classes that are using the decorator pattern if I want to expose it to everyone.

It seems like there should be an easier way to do this. I mean in theory you could implement a language capability to handle decorator pattern almost exactly the same as we handle extending a class; except instead of a making calls to super make calls to decorated class. If a method of the decorated class is called and the decorator doesn't have anything written for it pass the call down to the decorated class automatically. If the decorating class wants to hide the method, only if the decorating class wants to implement different logic does he have to actually write the full method out. Perhaps with some nice annotation to allow one to quickly identify what methods of decorated class should be made available and what shouldn't

so is there anything that will do this sort of logic for me? I mean I doubt it is built into java laungae itself like I described above, as cool as that would be it hardly seems like it would come up often enough to justify it. Still, does at the very least eclipse handle autowraping of methods like this or something?

Upvotes: 2

Views: 405

Answers (1)

FrankieTheKneeMan
FrankieTheKneeMan

Reputation: 6800

Well, kind of. I think you're under-utilizing the object oriented world. With an abstract class, you can implement default decorator behaviour, such as wrapping all the boring wraps. Then you can simply extend this Decorator abstract class and cherry pick the things you're overriding!

Something like this:

Decoratee.java

public interface Decoratee {
    public int methodA(int argument);
    public int methodB(int argument);
}

DecorateeA.java

public class DecorateeA implements Decoratee {
  private final Object arg1, arg2;
  public Decoratee(Object arg1, Object arg2){
    this.arg1 = arg1;
    this.arg2 = arg2;
  }
  public int methodA(int argument){
    return someInt;
  }
  public int methodB(int argument){
    return someInt;
  }
}

Decorator.java

public abstract class Decorator implements Decoratee {
  private final Decoratee decoratee;
  public Decorator(Decoratee decoratee){
    this.decoratee = decoratee;
  }
  public int methodA(int argument){
    return decoratee.methodA(argument);
  }
  public int methodB(int argument){
    return decoratee.methodB(argument);;
  }
}

DecoratorA.java

public class DecoratorA extends Decorator {
    public DecoratorA(Decoratee decoratee){
      super(decoratee);
    }
    public int methodA(int argument){
      return someOhterInt;
    }
    //methodB inherited from Decorator
}

DecoratorB.java

public class DecoratorB extends Decorator {
    public DecoratorB(Decoratee decoratee){
      super(decoratee);
    }
    //methodA inherited from Decorator
    public int methodB(int argument){
      return someOhterInt;
    }
}

Yes, you still have to wrap these things. The upside here, is that you only have to wrap them once - then you can build decorators till you're blue in the face.

Additionally - if you need access to the decoratee's method's, you can now call them via the super keyword:

public class DecoratorC extends Decorator {
    public DecoratorC(Decoratee decoratee){
      super(decoratee);
    }
    //methodA inherited from Decorator
    public int methodB(int argument){
      return someOhterInt + super.methodB(argument);
      //super.methodB calls Decorator.methodB which calls decoratee.methodB;
    }
}

Upvotes: 0

Related Questions