1 前置閱讀
在閱讀本文章之前,你可以先閱讀:
- 什麼是DDD
2 實現值物件
值物件有兩個主要特徵:它們沒有任何標識。它們是不可變的。
我們舉個例子:小明是“浙江寧波”人,小紅也是“浙江寧波”人,小王是“浙江杭州”人,在這個例子中,我們把地址可以獨立出一個值物件出來,我們會遇到了多個物件是否相同的問題,例如小明和小紅的地址應該是相等,小明和小王應該是不相等,這很好理解,我們來看一下例子;
public class Address
{
public string Province;
public string City;
}
var xm = new Address { Province = "浙江", City = "寧波" };
var xh = new Address { Province = "浙江", City = "寧波" };
var xw = new Address { Province = "浙江", City = "杭州" };
Console.WriteLine(xm.Equals(xh));
Console.WriteLine(xm.Equals(xw));
讓我們來看看輸出結果:
False
False
這個顯然不符合我們預期,我們需要重寫一下Equals,確保地址值相等的情況下物件相等。
public class Address
{
public string Province;
public string City;
public bool Equals(Address obj)
{
return this.Province.Equals(obj.Province) && this.City.Equals(obj.City);
}
}
var xm = new Address { Province = "浙江", City = "寧波" };
var xh = new Address { Province = "浙江", City = "寧波" };
var xw = new Address { Province = "浙江", City = "杭州" };
Console.WriteLine(xm.Equals(xh));
Console.WriteLine(xm.Equals(xw));
讓我們來看看輸出結果:
True
False
這個顯然符合我們預期了,接下來我們把值物件的Equals方法封裝到基類中。
public abstract class ValueObject
{
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
}
public class Address : ValueObject
{
public string Province;
public string City;
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Province;
yield return City;
}
}
3 實現實體
實體主要特徵:具有唯一標識。
前面我們講到值物件將特定值都相等的物件視為相等物件,在實體中比較容易理解,標識相等的物件視為相等物件。
public abstract class Entity
{
#region IEntity Members
public abstract Guid Id
{
get; set;
}
#endregion
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
if (Object.ReferenceEquals(this, obj))
return true;
if (this.GetType() != obj.GetType())
return false;
Entity item = (Entity)obj;
return item.Id == this.Id;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
4 實現聚合根
聚合根與實體的區別,實體只在聚合內部進行操作,聚合根是對外打交道的唯一實體。我們在這裡設計時聚合根需要有增改刪狀態欄位。
public enum AggregateState
{
Added = 1,
Updated = 2,
Deleted = 3
}
public abstract class AggregateRoot : Entity
{
#region IAggregateRoot Members
public AggregateState AggregateState { set; get; }
#endregion
}