在观察者模式中,我们是否应该使用弱引用?

6
我正在学习并尝试从这个教程中在Java中实现观察者模式。我卡在了一个问题上,就是关于我是否应该使用WeakReference来让主题持有观察者。
在下面的实现中,SubjectBinaryObserver互相持有强引用,这让我担心防止GC回收未使用的Subject
所以我的问题是,我是否应该使用List<WeakReference<Observer>> observers代替List<Observer> observersSubject.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);
    }
}

弱引用很糟糕,只有在你喜欢追踪错误时才使用它们。注意:Java的垃圾回收器是智能的。 - Sleiman Jneidi
2
让我修改@SleimanJneidi的说法:Java的GC非常聪明。它基于“可达性”原则工作-如果SubjectObserver都不是“可达”的(本质上是:没有办法从以main()方法中的对象为起点的任何对象引用链中获取到它们),那么它们可以被收集。它并不关心它们彼此引用。这些引用仅确保如果一个是可达的,则另一个也是可达的。如果两个都不可达,它不会无谓地将它们保持活动状态。 - dcsohl
谢谢,但我们什么时候应该使用“弱引用”(WeakReference)呢?我认为观察者模式是使用“弱引用”的一个很好的例子,因为在C++中,观察者模式对于“weak_ptr”有很好的示范作用... - hackjutsu
如果您希望程序依赖于GC的行为而变得不可预测,可以使用WeakReference。 - Sleiman Jneidi
只要相信垃圾回收器。如果你担心性能问题,可以尝试不同的配置:gc类型(g1、parallel等)、年轻代空间等。 - Kaputnik120
1个回答

2

在您的情况下,您不必使用弱引用。您所做的是可以的。Java GC已经处理了循环引用。如果循环引用图形是孤立的(从根没有传入引用到图形 - 您可以认为整个图形是一个大对象,如果没有引用,则GC将收集此大对象),则Java GC将收集整个循环引用图形。

看一下这个:Java垃圾回收如何处理循环引用?


1
在Subject有意被保留而观察者需要被回收的情况下,我强烈反对这种做法。Subject不应该被认为是持有Observer的引用(应该是相反的),因此它持有一个强引用是语义上错误的。循环引用并不是问题,浮动垃圾才是问题。 - saolof

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接