Search code examples
javadesign-patternsinheritancedynamicextend

Java architecture issue for extending instances (need for a pattern recommendation)


A service from external API which I am not allowed to modify returns me

  MyClass instance = ServiceUtil.getThing();

I would like to extend this returned class and Add/Override a method but leave intacts the others, say 150 methods.

  private class MyWrapperClass extends MyClass(){
      public MyWrapperClass(){super();}
      @Override public String toString(){ return "Blocked toString"; }
  }

Is there any way to force this "casting" from the returned MyClass instance to my newly particular subtype??

NOTE: Please, not suggest the approach of making a constructor, passing the original object and having to copy and implement the 150 methods to call the wrapped object


Solution

  • If MyClass is an interface look at java.lang.reflect.Proxy and java.lang.reflect.InvocationHandler.

    You can implement a dynamic proxy that always does the same. It is, always pass control to your original implementation... except when method X is invoked.

    Something like:

    class MyHandler implements InvocationHandler {
      Object invoke(Object proxy, Method method, Object[] args) {
        if (method is the one you want to change) {
           do whatever
        else
           return method.invoke(originalObject, args);
      }
    }
    

    Note: you must create this proxy implementation anyway:

    MyClass original = ServiceUtil.getThing();
    MyClass proxy = (MyClass) Proxy.newProxyInstance(
                                              MyClass.class.getClassLoader(), // classloader to use
                                              new Class[] { MyClass.class }, // interfaces to implement
                                              new MyHandler()); // who does the dirty work when methods are invoked