2009-08-24 130 views
3

如果addListener方法調用時檢查重複的註冊?如果是這樣,發現重複時會發生什麼?註冊Java事件時,通常允許重複偵聽器嗎?

final public class exampleCanFire { 
    public void addFooListener(FooListener listener) { 
     // Before adding listener to private list of listeners, should I check for duplicates? 
    } 
} 
+2

儘管我不知道從圖書館設計的角度看,答案是肯定的,圖書館唯一一致的做法是註冊所有聽衆(包括重複內容)?否則,如果兩個不同的子系統偶然註冊了同一個監聽器,那麼第一個註銷它將會弄亂另一個子系統 - 對嗎? – 2009-08-24 09:23:55

+1

它會像收到每個事件兩次一樣,因爲其他人重新註冊您的監聽器。 – Zed 2009-08-24 09:26:07

+0

@Zed:是的,但我認爲那是不小心組合了兩個子系統的人的錯。它必須是組合無關「對等」子系統以瞭解它們將如何相互作用的人的責任 - 因爲替代方案是讓每個子系統知道如何與當前存在或可能存在的每個其他無關「對等」子系統交互未來,這是不可行的。 – 2009-08-24 11:22:04

回答

4

我的選擇是將它們存儲在一個List,而不是重複檢查。這種方法的一些優點:

  • 監聽器以確定性的順序通知,並可能將事件標記爲「消耗」,導致它們不傳播給後續監聽器。
  • 人們可以使用CopyOnWriteArrayList實現,它允許聽衆沒有飛出ConcurrentModificationException通知回調過程中,除去本身(這是非常重要,是編寫面向事件的代碼時,一個典型的疑難雜症)。
+1

對於'CopyOnWriteArrayList' +1。 – Bombe 2009-08-24 09:39:02

+0

第一點是完全有效的,但在第二點上,現在也有可用的CopyOnWriteArraySet,它可能會用於替代。但是,使用列表仍然可能是最好的選擇,確保沒有註冊重複的監聽器應該由客戶端提供 – 2014-06-30 13:03:46

3

我不認爲有檢測重複偵聽器的指定行爲。我會說,除非你正在編寫一個事件處理框架,否則最好不要麻煩檢查。如果一個類將自己註冊爲偵聽器兩次,那麼它就是調用代碼中的錯誤,而不是可觀察對象中的錯誤。

如果你確實想做點什麼,我只是建議扔一個IllegalArgumentException,說明你不能註冊同一個監聽器兩次的消息。

0

商店他們在一個組,並傳播任何設置的迴應是:

Set<FooListener> listeners = new HashSet<FooListener>(); 

public boolean addFooListener(FooListener listener) { 
    return listeners.add(listener); 
} 
0

如果使用列表發現比使用JAVA推薦的方法要慢很多。我的猜測是JAVA的方法有更直接的內存交互,或者什麼的。無論如何,我同意j_random_hacker的意思,你應該知道什麼時候會發生什麼情況,並且隨後冒着重複聽衆混淆其他人的行爲的風險,但這就是爲什麼我們測試我們的程序,是不是;-)

相關問題