Я считаю, что я видел варианты этого вопроса, но не «окончательный ответ». В приведенном ниже коде я понимаю, что SomeEventManager содержит ссылку на someImplClassTwo.myEventListenerA и someImplClassTwo.myEventListenerB и что это не позволяет некоторому implClassTwo быть собранным мусором, и это приводит к выходу, сгенерированному во второй раз, когда someEventManager.notifyListeners() является вызывается.Есть ли «чистый» способ автоматической регистрации регистратора в Java?
Но я бы очень хотел, чтобы пользователи SomeImplClass не знали, что есть слушатели, участвующие в реализации, и что эти слушатели должны быть вручную незарегистрированы (например, SomeImplClass.releaseListeners()) до освобождая объект SomeImplClass.
Есть ли чистый/принятый способ сделать это?
p.s. Я уже играл с finalize(), просто для удовольствия, и подтвердил, что GC даже не пытался в этом случае, для любого экземпляра SomeImplClass. Таким образом, это, кажется, не стартер, как потенциальное решение.
Test Driver
public class TestDriver {
public static void main(String[] args) {
SomeEventManager someEventManager = SomeEventManager.getInstance();
SomeImplClass someImplClassOne = new SomeImplClass("One");
SomeImplClass someImplClassTwo = new SomeImplClass("Two");
someEventManager.notifyListeners();
someImplClassOne.releaseListeners();
someImplClassOne = null;
someImplClassTwo = null;
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
someEventManager.notifyListeners();
}
}
Интерфейс Event
public interface SomeEventListener {
public void handleSomeEvent();
}
Event-менеджер
import java.util.ArrayList;
import java.util.List;
public class SomeEventManager {
private static SomeEventManager eventManager = null;
private List<SomeEventListener> listeners = null;
private SomeEventManager() {
listeners = new ArrayList<SomeEventListener>();
}
public static SomeEventManager getInstance() {
if (eventManager == null) {
eventManager = new SomeEventManager();
}
return eventManager;
}
public void addListener(SomeEventListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public void removeListener(SomeEventListener listener) {
listeners.remove(listener);
}
public void notifyListeners() {
for(SomeEventListener listener : listeners) {
listener.handleSomeEvent();
}
}
}
Event Listener Реализация
public class SomeImplClass {
private InnerEventListener myEventListenerA = null;
private InnerEventListener myEventListenerB = null;
private String id = null;
public SomeImplClass(String id) {
this.id = id;
myEventListenerA = new InnerEventListener(id + "_A");
myEventListenerB = new InnerEventListener(id + "_B");
}
public void releaseListeners() {
myEventListenerA.unregisterListener();
myEventListenerB.unregisterListener();
}
private class InnerEventListener implements SomeEventListener {
private SomeEventManager someEventManager = null;
private String id = null;
public InnerEventListener(String id) {
someEventManager = SomeEventManager.getInstance();
this.id = id;
registerListener();
}
public void registerListener() {
someEventManager.addListener(this);
}
public void unregisterListener() {
someEventManager.removeListener(this);
}
public void handleSomeEvent() {
System.out.println("InnerEventListener->" + id);
}
}
}
См. ['WeakHashMap'] (http://stackoverflow.com/questions/5511279/what-is-a-weakhashmap-and-when-to-use-it) –