Monday, February 20, 2017

Enhancing (extending) a class using dynamic proxy classes in Java

The Decorator Design Pattern is quite simple to understand and implement. Usually, in its simple form, it goes like this: In this example we have an interface A with a concrete implementation AImpl. We then implement ADecorator, a concrete decorator which wraps an instance of A and decorates the return value of the foo method.

We can also use this pattern not just to decorate but also enhance with additional functionality (like in java.io.Reader implementations). Continuing our example above, with some changes: In this example we did not want to change the return value of foo(), we wanted to enhance the functionality of A, in this case with the additional method bar(). Now, think about what would happen if A had more than one method. You would have to implement all those methods and delegate to the encapsulated instance of A.

Enhancing Using Dynamic Proxy Class

A way to avoid all this work and verbose code is to use Dynamic Proxy Classes:
In this example we define BImpl which is a private implementation of B - an interface with the extended functionality. BImpl takes an instance of A and encapsulates it so it can use it for its implementation. The create method creates a proxy object for interface AB (which is A & B). In the proxy, for each method we delegate to the corresponding object according to the origin class of the method.

Limitations


  1. This implementation relies on the knowledge that A and B are distinct - there are no shared methods. Otherwise we might delegate to the wrong object.
  2. Overriding a method from A in the proxy is possible but requires more effort to do it right and robust (mainly to method renaming).