3

I was refactoring some java to use decorators. All of the decorators inherited from a class ThingDecorator, let's say. This consisted entirely of:

SomeType methodName(OtherType otherThing) {
    return decoratedObject.methodName(otherThing);
}

For maybe 20 methods of that form. This is like writing "this thing is a decorator" over and over again, which just drives me nuts as a DRY enthusiast. Every addition to the activities of this class needs an addition to the class[es] that form the basic un-decorated behavior and the decorator, but it's always just "this thing is still a decorator!" all over again. Is there any way to express once that an object is to delegate all non-overridden methods to some member field?

sqykly
  • 219
  • 1
  • 7
  • You *might* be able to do it with a compile time annotation, not certain. However, even if you could, it would confuse IDEs something horrible. –  Nov 28 '15 at 03:38
  • Unless the base decorator is a class stating the contract, I see no reason why you would want to inherit from it, you might as well just use an interface. This seems like a violation of LSP. – Andy Nov 28 '15 at 07:10
  • @davidpacker for the purpose of the question it doesn't matter, but the real project had an interface `AbstractThing` that was the contract, a `BasicThing implements AbstractThing` that was the default behavior of a `Thing`, a `ThingDecorator implements AbstractThing` whose *only* task was to have a reference to an `AbstractThing` and delegate all calls to it, a plethora of `ThingWithSomeStuff extends ThingDecorator` which provided *only* the concrete meaning of the `Thing` having some `Stuff`, and finally a `ThingToPointAt` for hiding the decoration from things that don't know they need it. – sqykly Nov 28 '15 at 13:02
  • @davidpacker (cont) in the more complete picture, it should be clear that both levels of abstract hierarchy are puposeful - the interface defines the contract, the `BasicThing` fulfills the contract provided by the interface, the abstract base decorator ensures that any concrete decorator that doesn't fulfill the entire contract has a reference to a thing that can and uses it to do so without needing to understand the entire contract of a `Thing` when all you want is for it to have some `Stuff`. – sqykly Nov 28 '15 at 13:32
  • @davidpacker final clarification because that sounds overcomplicated otherwise: there were many different kinds of `Stuff` that could affect a `Thing` and many different kinds of `Thing`, and new kinds of `Stuff` were being added with every revision. Before I got there, all `Stuff` had to be defined, considered, and managed throughout the `Thing` that it affected. It was already quite complicated, my way is actually a lot neater. – sqykly Nov 28 '15 at 13:55

1 Answers1

2

No, unfortunately, there isn't any way to accomplish this.

Unless you use some magic, like this: michael.gr - Intertwine: Normalizing Interface Invocations (which though I have implemented for C#, not for Java yet.)

Mike Nakis
  • 32,003
  • 7
  • 76
  • 111
  • I hover around the use of magic (technically I guess it's code generation or macros, though we don't like using the word anymore thanks to C) and hesitate because I worry that no one will ever be able to just pick up my code and read it knowing plain old java. Right after I wrote this question, I wrote a sweet.js macro for it, but I just know that as dry and beautiful as it is, I can never use it in a serious project. Depressing. – sqykly Nov 28 '15 at 04:05
  • I am giving the question a little more time, but I am not forgetting a check mark for the "there is no answer" answer if no one can come up with some miracle. – sqykly Nov 28 '15 at 06:36