2008-09-18 68 views
7

我一直在想了一會兒這個面向對象的設計問題,現在都無法拿出一個滿意的解決方案,所以想我應該把它開到人羣這裏一些意見。OO設計,開/常閉原則問題

我有一個遊戲類代表一個回合制棋盤遊戲,我們可以假設它類似於這個問題的壟斷。 在我的設計,我有一個包含方法TakeTurn一個球員類。

遊戲遍歷所有球員 S和調用TakeTurn方法做一切必要的事情來完成轉彎。 我想能夠擁有n個玩家,並且能夠將他們的任意數量設置爲電腦玩家。 所以,我的想法是有一個HumanPlayer類和一個類,這兩個類都派生自Player。

遊戲只知道球員,並簡單的呼籲依次在每個球員TakeTurn方法。 我的問題在於事實上,物體可以完全自動化,即與Monopoly示例保持一致,可以決定使用某些邏輯來購買物業。 現在,隨着HumanPlayer對象,它需要得到實際用戶的輸入,能夠買實例中的屬性,這似乎意味着不同的接口,可能意味着他們不應該得到

我一直沒能拿出一個很好的解決問題,而不必在遊戲類瞭解各種播放器的實際實現類中明確。我總是可以假設在遊戲中,只有人類和電腦玩家纔會這樣做,並且有效地關閉它以延伸,但它看起來並不是很好的OO編程。

對此的任何意見將不勝感激。

+0

我不確定[tag:open-closed-principle]在這裏適用。 – Fuhrmanator 2012-04-18 12:51:43

回答

7

我認爲你不應該讓Game類處理IO。這種方式,(阻擋)TakeTurn方法將會從遊戲板中隱藏執行的手段。它可以使用其他對象與用戶進行通信。

所有的遊戲類應該關注的是董事會的狀態和轉折點。玩家都應該實現一個單一的球員界面,並隱藏遊戲中的所有實施。

+0

+1努力提供遊戲良好*凝聚力*(適當的責任)。 – Fuhrmanator 2012-04-18 12:50:22

1

與其告訴遊戲類,只有永遠一個人,爲什麼不讓它在遊戲的菜單/初始化過程中獲取輸入?如果有更多的玩家,那麼可以通過某種形式的輸入來決定(在菜單中選擇玩家),在遊戲類初始化之前。

0

我覺得Game類不應該對玩家級別任何實現的關注,同時也忽略了用戶界面。

任何用戶輸入需要通過HumanPlayer類進行處理。

1

球員呈現給遊戲接口垂直於衍生球員類的行爲。

該實現的TakeTurn取決於具體類型的球員對象不應該是令人擔憂的事實。

0

林我不知道這是否是你想要

public abstract class Player 
{ 
    int position; 
    DecisionMaker decisionDependency; 

    ... 

    public void TakeTurn() 
    { 
    position += RollDice(); 
    GameOption option GetOptions(position); 
    MakeDescion(option); 
    } 

    protected int RollDice() 
    { 
    //do something to get the movement 
    } 

    protected abstract void MakeDecision(GameOption option); 

} 

Public class ComputerPlayer : Player 
{ 
    public ComputerPlayer() 
    { 
    decisionDependency = new AIDecisionMaker(); 
    } 

    protected override void void MakeDecision(GameOption option) 
    { 
    decisionDependency.MakeDecision(option); 
    //do stuff, probably delgate toan AI based dependency 
    } 
} 

Public class HumanPlayer : Player 
{ 
    public HumanPlayer() 
    { 
    decisionDependency = new UIDecisionMaker(); 
    } 

    protected override void void MakeDecision(GameOption option) 
    { 
    decisionDependency.MakeDecision(option); 
    //do stuff, probably interacting with the a UI or delgate to a dependency 
    } 
} 
+1

請縮進你的代碼,這很難理解。 – 2008-09-18 16:10:20

0

我說什麼,該遊戲類不應該關心如果這是一個電腦玩家或人類玩家。它應該始終在下一個玩家類別上撥打TakeTurn。如果這是一個人類玩家,它是類的責任,與用戶溝通並要求用戶該做什麼。這意味着它會阻止,直到用戶下定決心。由於通常UI交互發生在應用程序的主線程中,因此阻止TakeTurn不會阻止整個應用程序,否則用戶輸入無法處理,而遊戲等待TakeTurn

2

如果遊戲正在管理遊戲狀態做I/O,那麼遊戲做得太多了。

你想讓遊戲緊緊集中在規則,輪到和狀態變化上。 遊戲並不知道玩家是什麼;它只知道它有玩家。

您希望玩家在輪迴期間檢查遊戲狀態並執行法律行爲。

人類運動員和整個遊戲共享一個共同的I/O包,顯示遊戲狀態並提示人類的輸入。

通過使遊戲的I/O包爲Observer,可以充分利用Java Observable。這樣,遊戲狀態更改就會報告給I/O以進行顯示或記錄,或者兩者兼而有之。

0

取而代之的是遊戲類調​​用TakeTurn上所有球員的球員應該叫TakeTurn遊戲類如果有合適的球員,走的是遊戲類應驗證輪到他了。

這應該有助於解決用戶計算機球員的問題。

2

我可能沒有兩個HumanPlayerComputerPlayer類,但是一個Player類在創建時使用正確的輸入策略進行配置。

玩家獲得的信息來決定在遊戲的下一回合的移動方式是唯一件事變化(從原來的問題描述,至少),所以只是封裝在一個單獨的抽象。

無論設置遊戲的高級別玩家還應該創建兩組玩家(一個人,另一個計算機模擬),併爲每個玩家設置適當的輸入策略,然後只需將這些玩家對象分配給遊戲目的。遊戲類將只在給定的玩家列表上調用TakeTurn方法,用於每次新的回合。

+0

+1支持合成而不是繼承。 – Fuhrmanator 2012-04-18 12:49:02