6

I'm learning and trying to implement the Observer pattern in Java from this tutorial. I'm stuck at the point about whether I should use WeakReference for the subject to hold the observers.

For the implementation below, the Subject and the BinaryObserver are holding strong references to each other, which I'm afraid prevents GC from collecting the unused Subject.

So my question is, should I use List<WeakReference<Observer>> observers instead of List<Observer> observers?

Subject.java

public class Subject {

   private List<Observer> observers = new ArrayList<Observer>();
   private int state;

   public int getState() {
      return state;
   }

   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }

   public void attach(Observer observer){
       observers.add(observer);
   }

   public void notifyAllObservers(){
       for (Observer observer : observers) {
           observer.update();
       }
   }
}

Observer.java

public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}

BinaryObserver.java

public class BinaryObserver extends Observer{

    public BinaryObserver(Subject subject){
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Binary String: " + Integer.toBinaryString());
    }
}

ObserverPatternDemo.java

public class ObserverPatternDemo {
    public static void main(String[] args) {
       Subject subject = new Subject();

       new BinaryObserver(subject);

       System.out.println("First state change: 15");
       subject.setState(15);
    }
}
hackjutsu
  • 8,336
  • 13
  • 47
  • 87
  • weak references are evil, only use them if you like chasing bugs. Note: Java's GC is smart – Sleiman Jneidi Nov 02 '15 at 20:13
  • 2
    Let me amend @SleimanJneidi's statement: Java's GC is *very* smart. It works on the basis of "reachability" - if neither `Subject` nor `Observer` are "reachable" (essentially: there's no way to get access to them from any chain of object references starting with objects in the `main()` method), then they can be collected. It does not matter that they reference each other. Those references only ensures that if one is reachable, then the other is too. It won't needlessly keep them alive if neither is reachable. – dcsohl Nov 02 '15 at 20:18
  • Thank you~ but when should we use `WeakReference`? I thought the Observer pattern was a good example for `WeakReference`, since in C++ the oberser pattern shows good example for `weak_ptr`... – hackjutsu Nov 02 '15 at 20:23
  • @Hackjustu u use WeakReference if you want your program to be unpredictable relying on the behaviour of the GC – Sleiman Jneidi Nov 02 '15 at 20:26
  • Just trust the GC. If you are concerned about performance, rather try different configurations: type of gc (g1, parallel,...), young gen space, etc. – Kaputnik120 Nov 02 '15 at 20:31

1 Answers1

2

You don't have to use weak references in your case. What you are doing is fine. Java GC already handles Circular References. Java GC will collect an entire Circular References graph if it (graph) is an ISLAND (No incoming references to the graph from the Root - You can think the entire the graph is a big Object and the GC will collect this big object If there is no references to it)

Take a look at this: How does Java Garbage Collection work with Circular References?

LHA
  • 9,398
  • 8
  • 46
  • 85
  • 1
    I strongly disagree with this in the situation where the Subject is intentionally never GCd while the observers need to be GCed. The Subject should never be thought of as having a reference to the Observer (it should be the other way around), so it is semantically wrong for it to hold a strong reference to it. Circular refs are not the problem, floating garbage is – saolof Feb 23 '23 at 23:39