2009-12-26 106 views
13

有沒有辦法避免循環依賴,比混合模塊,在這樣的佈置之外循環依賴(這是一款國際象棋應用程序)如何避免此

長描述:

  • Gui模塊,它導入一個ChessWidget模塊;
  • ChessWidget只是包裝ChessWorld模塊和進口CellButton;
  • CellButton模塊導入模塊Cell;
  • ChessWorld模塊導入Board(表示它)和Players(通知他們並取回他們的動作);
  • Board模塊進口模塊Piece;
  • Piece模塊進口模塊Player;

這裏的問題是:

Player模塊需要了解其他玩家和電路板,從而導入ChessWorld

簡短說明:

World模塊需要知道關於Player模塊(甚至間接Board/Piece)和Player需要了解World

幫助非常感謝。

PS:不是因爲我不能使用循環依賴,而是因爲它們是邪惡的。

回答

14

按照Dependency inversion principle:引入一個接口,該接口ChessWorld器具,並在其上Player取決於 - 和/或一種其Player工具和其上Piece取決於(任一者或這取決於上的性質的細節都可能是適當的依賴)。這通常與Dependency Injection一起,並且,如果相關方需要動態實例化一些相關實例,則使用Factory DP。

+0

恕我直言,這不解決循環依賴。它仍然存在,但由DI容器處理並通過接口鬆散耦合。 – Cohen 2010-01-07 10:22:19

+7

相關性有一個方向,例如A-> B-> C-> A是圓形的,但如果你反轉任何一個箭頭,它不再是一個圓。 – 2010-01-07 15:46:24

0

我要堅持我的手在這裏說...恕我直言,你可能已經過度設計了這一點。

爲什麼一件作品需要了解玩家的知識?棋子是黑色或白色,無論誰在控制(玩)它。

你提到「player module」和「piece module」 - 爲什麼它們是單獨的模塊?爲什麼它們不只是數據類(域對象)在同一個模塊中?

如果我已經分析過這個問題,或者無法理解你是如何構建你的遊戲的,那麼通過一切手段無視我說的話。 OTOH也許我確實讀了正確的東西?

+0

這是因爲是一個國際象棋變體系統,所以它是2板7球員和制裁規則 – zaphnat 2009-12-26 01:33:35

+0

嗯好的,這將解釋它:) – slugster 2009-12-26 06:31:44

2

考慮每個對象真正需要什麼,而不是現在需要的東西。

一件物品可能不需要知道一個玩家 - 它需要知道的是它可以發送更新的東西。

因此,對於這個例子,創建一個代表「PieceMessageListener」或類似的接口,並讓Player實現它。現在,兩個結核都取決於抽象(遵循「結核應取決於抽象,抽象不應依賴於結核」的規則)。

5

我認爲循環依賴的氣味顯示出更多的架構/設計問題,這不應該通過DI,後期邊界,鬆散耦合或任何其他形式的額外抽象層來解決。儘管它們都是非常好的機制,但不解決下面的問題。

短:我認爲國際象棋世界持有太多的責任。如果你把它們分開,你可能會發現依賴關係更適合在單獨的模塊中。

很長的解釋:我會試着給出一個例子,說明如何重構它,雖然這很難,因爲我現在不是真正的完整問題域。

注意:我對Java不熟悉,所以我可能會誤解導入和包裝的含義。

但據我瞭解的依賴性看起來有點像這樣:

Gui <- ChessWidget <- ChessWorld <- CellButton <- Cell 
           <- Board <- Piece <- Player 
           <- Players <- ChessWorld 

恕我直言,問題是ChessWorld擁有太多不同的責任。在PlayerList,RegisteredUsers或OnlineUsers之類的單獨模塊中維護玩家列表可能會更好。在重構之後,你的依賴會改變如下:

Gui <- ChessWidget <- ChessWorld <- CellButton <- Cell 
            <- Board <- Piece <- Player 
            <- Playerlist <- Player 

PlayerList可能是你在播放器模塊中的東西。現在國際象棋世界取決於玩家模塊而不是其他方向。

我不確定它是否完全符合您的意圖,但我非常有興趣討論此事,所以請發表評論。

+0

問題是,仍然,該球員需要知道董事會,甚至其他球員。我使用了一個解決方案,將片段和播放器模塊分開,通過使用「鍵」或ID,然後執行世界實現和Player導入的WorldInfo接口。這樣,進口板,並不意味着進口一塊。 – zaphnat 2010-01-08 06:34:00