1
\$\begingroup\$

I have 3 classes: a transmitter, a view for displaying and a recording view for flushing the screen contents into a file. The view and the recording view classes register themselves from their constructor in the transmitter, which keeps them in a HashMap. The transmitter implements all the view and recording view classes' interfaces, and delegates the incoming method invocations to them based on the actually registered implementors.

To make things clear:

public interface IRecordingView {
  public void recordingViewMethod1();
  public void recordingViewMethod2();
}

public class RecordingView implements IRecordingView {
  public RecordingView {
    Transmitter.getInstance().register(this);
  }

  @Override public void recordingViewMethod1() { ... }
  @Override public void recordingViewMethod2() { ... }
}



public interface IView {
  public void viewMethod1();
  public void viewMethod2();
}

public class View implements IView {
  public View() {
    Transmitter.getInstance().register(this);
  }

  @Override public void viewMethod1() { ... }
  @Override public void viewMethod2() { ... }
}



public class Transmitter implements IRecordingView, IView {
  private static final Transmitter instance = new Transmitter();
  private HashMap<Class, Set> register = new HashMap<Class, Set>();

  public Transmitter() {
    for (Class cl : this.getClass().getInterfaces()) {
      register.put(cl, new HashSet());
    }
  }

  public void register(Object listener) {
    for (Class interf : register.keySet()) {
      if (interf.isInstance(listener)) {
        Set implementors = register.get(interf);
        implementors.add(listener);
      }
    }
  }

  @Override public void viewMethod1() {
    for (IView delegate : register.get(IView.class)) {
      delegate.viewMethod1();
    }
  }

  @Override public void recordingViewMethod1() {
    for (IRecordingView delegate : register.get(IRecordingView.class)) {
      delegate.recordingViewMethod1();
    }
  }

  // and so on for the rest of the methods
}

This is the basic concept of the legacy code. Of course there are many transmitters, each implementing more interfaces, with each interface having more methods. Is there an optimal and/or elegant way to further reduce code size? The delegation mechanism looks quite the same in every method, but I don't want to mess with reflection.

\$\endgroup\$
  • 1
    \$\begingroup\$ Why no reflection? Have you considered code generation (compile time or runtime)? \$\endgroup\$ – Joe F Apr 23 '13 at 16:53
  • \$\begingroup\$ This is a real-time diagnostic measurement tool, I can't afford any performance issues which I'm mostly afraid of. However, I'll do some benchmarking tomorrow to see if any delays occur. Thank you anyway for the support :) \$\endgroup\$ – András Hummer Apr 23 '13 at 21:04
  • \$\begingroup\$ Well, I finally decided to do it with reflection and it seems to do the trick. Please add your comment as an answer so I can accept it :) \$\endgroup\$ – András Hummer Apr 25 '13 at 9:00
1
\$\begingroup\$

Why no reflection? Have you considered code generation (compile time or runtime)?


Here's an idea based on proxies and reflection. I haven't actually tried any of this, so the idea might break down at some point, but here goes.

Create an interface for the transmitter that extends all of the interfaces the transmitter will implement:

public interface ITransmitter extends IRecordingView, IView { ... }

Have the transmitter class implement that interface and return the singleton instance as that interface:

public class Transmitter implements ITransmitter {
    public static ITransmitter getInstance() { ... }
}

The instance returned is actually a proxy created using java.lang.reflect.Proxy with an InvocationHandler that will delegate the appropriate method invocations using reflection.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.