值對象
表示描述性的、欠缺身份的概念
比如"余額",在大多數領域中,你會單獨查詢"余額"嗎?不會,因為獨立的"余額"沒有任何意義,他必須附屬于某一個實體才會擁有自身的概念
增強明確性
DDD的一切都是為了明確傳遞重要業務規則和領域邏輯,如果用字符串、整型這類基元類型的話,并不適合描述概念,所以,應該組合基元類型,并封裝成明確表示其正在建模的高內聚對象
比較
盡管值對象沒有身份,比較他們也是是至關重要的操作。通過他們的特性或價值來比較相等性
富含行為
值對象應該盡可能多的公開具有表述性的面向領域行為并封裝狀態。默認來說,所有基元類型都應該是私有的或受保護的(實體也是如此) 如:public string Name{get; private set;} ,只有當有足夠合理的理由時,才能打破封裝讓其變成公共的
自驗性
值對象必須保證狀態有效(實體也是如此),它們自身就要單獨負責確保滿足這一需求,當創建值對象實例時,如果參數與規則不一致則構造函數里必須拋出異常。如Money可能會有兩個領域規則:1.精確到兩位小數。 2.不能為負數
不可變
一旦創建則不可變,每次修改都是返回新實例,因為不可變性通常更易于推斷,并且天然屬于線程安全,它只有很少的危險意外影響。并且不可變對象性能更好,因為為了保證對象狀態完整性(避免數據撕裂)一般都會加鎖,而不可變對象由于每次都返回新實例,永遠都是數據完整的,所以不用加鎖操作,不過這也是缺點,當每次對象/集合操作都會返回個新值,而舊值依舊會保留一段時間,這會使內存有極大開銷,也會給GC造成回收負擔,如果某個場景需要在兩種方式選擇其一的話,一般情況還是返回新對象為優先選擇。.NET里的DateTime就是一個不可變性的經典示例。不可變性還會支持可組合性:組合起來以創建新的值,如Money + Money = new Money
public class Money : ValueObject<Money> { protected readonly decimal Value; public Money() : this( 0m ) { } /// <summary> /// 構造函數創建,當創建邏輯簡單時應用構造函數創建 /// </summary> public Money( decimal value ) { if( value % 0.01m != 0 ) { throw new Exception( "必須精確到兩位小數" ); } if( value < 0 ) { throw new Exception( "不能為負數" ); } Value = value; } /// <summary> /// 工廠創建,當創建邏輯復雜時應用工廠創建 /// </summary> public static Money Create( decimal value ) { if( value % 0.01m != 0 ) { throw new Exception( "必須精確到兩位小數" ); } if( value < 0 ) { throw new Exception( "不能為負數" ); } return new Money( value ); } public Money Add( Money money ) { return new Money( Value + money.Value ); } public Money Subtract( Money money ) { return new Money( Value - money.Value ); } public static Money operator +( Money left , Money right ) { return new Money( left.Value + right.Value ); } public static Money operator -( Money left , Money right ) { return new Money( left.Value - right.Value ); } /// <summary> /// 值對象比較,基于特性 /// </summary> protected override IEnumerable<object> GetAttributesToIncludeInEqualityCheck() { return new List<object>() { Value }; } } class Program { static void Main( string[] args ) { var m = new Money( 100 ); var m2 = new Money( 50 ); var result = m - m2; var result2 = m + m2; } }

浙公網安備 33010602011771號