2015-10-19 96 views
2

假設我有一個具有「xp」值的User對象。現在說我有一個包含XPLevels數組定義多少點都需要這個水平(除其他事項外)的XPLevelsModel:從邏輯中分離數據

class User 
{  
    xp : int; 
} 

class XPLevelsModel 
{ 
    levels : XPLevel; 
} 

class XPLevel 
{ 
    ... 
    xpRequired : int; 
    name : String; 
    ... 
} 

好了,所以現在說我有許多方法,如「getCurrentLevel ()「」getPercentProgressThroughLevel()「等等這些方法應該在哪裏?

我可以把他們的用戶對象上:

class User 
{ 
    constructor(levelsModel:XPLevelsModel) : {} 

    xp : int; 

    getCurrentLevel() : int {} 
    getPercentProgressThroughLevel() : Number {} 
    ... 
} 

但是我們添加更多的數據,如「生活」,「健康」等等等等,用戶將開始有很多的功能(不是很好成長在SoC)

我可以嘗試組這些東西成組分,如「XPComponent」,這是對用戶的對象:

class User 
{ 
    xp : UserXPComponent; 
} 

class UserXPComponent 
{ 
    constructor(levelsModel:XPLevelsModel) {} 
    points : int; 

    getCurrentLevel() : int {} 
    getPercentProgressThroughLevel() : Number {} 
    ... 
} 

但問題是從靜止訪問該數據現在的遊戲意味着user.xp.getCurrentLevel(),它打破了Demeter的定律,再加上它的醜陋,難以測試,如果深度更深,會發生什麼?

還有一個選項,我想到了,能有這樣的:

class User 
{ 
    xp : int 
} 

class UserXPHelpers 
{ 
    constructor(levelsModel:XPLevelsModel) {} 

    getCurrentLevel(user:User) : int {} 
    getPercentProgressThroughLevel(user:User) : Number {} 
} 

這裏,我們已經分離出來的邏輯和數據,並通過方法傳遞給用戶。唯一的是,這是不是打破封裝?由於所有這些方法都依賴於用戶傳遞給他們,他們不應該與用戶住在一起嗎?

如果這是正確的解決方案,「助手」是否正確的名稱?

我希望你能幫助一次又一次地挑戰我的問題,並且現在只能將它表達爲一個查詢。

邁克

+0

您使用哪種語言?如果您只關心第一個選項是類大小,只需使用[擴展方法](https://msdn.microsoft.com/en-gb/library/bb383977.aspx)。 – sdgfsdh

+0

我儘量保持抽象,語言無關緊要。它更多的是一個普遍的問題 – mikeysee

回答

2

三個案例可以用在更好的選擇取決於凝聚力。換句話說,它取決於xpUser(無論是屬性還是聚合域實體或甚至屬於其他域)之間的關係。其他值如lives,health等可以有不同的解決方案。所以你不必適用於所有你的東西相同的方法,而且,我確定他們在你的域模型中扮演不同的角色。

1.高凝聚力(屬性),該值是父對象結構的一部分,父對象結構中沒有它的情況下不能存在。那麼它應該與第一個例子中的字段(屬性)和/或方法集一致。

儘管如此,xp似乎並非如此。

2.聚合實體,該值高度連接到父級(聚合根),但可以單獨使用。這是你的第二個例子XPComponent。因此,您可以決定XPComponent是否爲您網域的聚合實體。我沒有看到德米特的法律在這裏遇到很大的麻煩,因爲它在更高級別的系統架構上有意義,see also

3.獨立實體。它只對父級提及。這不是xp的情況。

4.服務功能。所以它既不是實體也不是域模型的一部分。在這種情況下,您可以使用您的Helpers解決方案,該解決方案實際上是一項域服務。