2

In JAVA I often use this pattern:

class A{
    void addListener(Listener obj);  
    void removeListener(Listener obj);
}

class B {
    private A a;

    B(A a){
        this.a=a;
        a.addListener(myListener)
    }

    private final myListener=new Listener(){
        void listener(); 
    }

    public void dispose(){
        a.removeListener();
    }
}

Typically A represents a dataset and B needs to respond to changes of the data in A. This is done by adding a listener to the object a when a new B instance is constructed.
Since the object a exists outside A, this approach forces me to create a dispose() method, that removes the listener from the object a.

Though I know that well designed JAVA code typically does not need dispose() methods. Is this pattern a poor design? Can you suggest alternative approaches?

Thanks in advance for your help.

1 Answers1

0

Typically I avoid constructors which require A as an argument. A pattern with a no-argument constructor is simpler to read, allows for serialisation, allows for more flexible re-use of objects etc.

Also in your code, there is a period of time, after dispose is called, in which you have a 'disconnected' B. You have to handle the error conditions if methods get called in this period of time.

So, to make it more foolproof:

class B {
  private A a=null;

  B(){}

  public connectToA(A a){
    if(a!=null) throw new RuntimeException(...);
    this.a=a;
    a.addListener(myListener)
  }

  private final myListener=new Listener(){
    void listener(); 
  }

  public void disconnectFromA(){
    if(a==null) throw new RuntimeException(...)
    a.removeListener();
  }
}

If you really want your connection to be present whenever B exists, and to be removed when B ceases to exist, consider trying to disconnect in the finalizer.

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
  • Your answer is more about favor as of pattern. If you **require** `a` to be set, it's ok to do this the constructor. – mad_manny Nov 13 '15 at 12:31
  • Agreed. There are many ways of accomplishing the same thing, but some are more explicit than others. **Requiring** `a` to be set gives problems after calling `dispose`. in which case overriding `finalize` might be the right solution? – Sanjay Manohar Nov 13 '15 at 12:33