5 建立實體
建立一個實體時,我們總期望通過構造器就能初始化足夠多的實體狀态,因為這樣更容易通過各種條件查找到該實體。
在使用及早生成唯一辨別的政策時,構造器至少需接受唯一辨別參數。若還有可能通過其他方式查找實體,比如名字或描述資訊,那應該将這些參數一并傳給構造器。
有時一個實體維護一或多個不變條件(Invariant,在整個實體生命周期中都必須保持事務一緻性的一種狀态) 。
不變條件主要是聚合所關注的,但聚合根也是實體。
如果實體的不變條件要求該實體所包含的對象都不能為null或必須由其他狀态計算所得,那麼這些狀态也需作為參數傳遞給構造器。
public class User extends Entity {
...
// 每一個User對象都必須包含tenantld、username, password和person屬性。
// 即在User對象得到正确執行個體化後,這些屬性不能為null
// 由User對象的構造器和執行個體變量對應的setter方法保證這點
protected User (Tenantld aTenantld
String aUsername,
String aPassword,
Person aPerson) (
this();
this.setPassword(aPassword);
this.setPerson(aPerson);
this.setTenantld(aTenantld);
this.setUsername(aUsername);
this.initialize();
}
...
protected void setPassword(String aPassword) {
if (aPassword == null) {
throw new 11legalArgumentException(
"The password may not be set to null.");
)
this.password = aPassword;
)
protected void setPerson(Person aPerson) (
if (aPerson == null) (
throw new IllegalArgumentException("The person may not be set to null.");
}
this.person = aPerson;
}
protected void setTenantld(Tenantld aTenantld) (
if (aTenantld == null) {
throw new IllegalArgumentException("The tenantld may not be set to null.");
}
this.tenantld = aTenantld;
}
protected void setUsername(String aUsername) (
if (this.username != null) {
throw new IIlegalStateException("The username may not be changed.n);
}
if (aUsername == null) {
throw new IllegalArgumentException("The username may not be set to null.");
}
this.username = aUsername;
}
User對象展示了一種自封裝性。在構造器對執行個體變量指派時,把操作委派給執行個體變量對應的setter方法,便保證了執行個體變量的自封裝性。執行個體變量的自封裝性使用setter方法來決定何時給執行個體變量指派。
每個setter方法都“代表着實體”對所傳進的參數做非null檢查,這裡的斷言稱為守衛(Guard)。setter方法的自封裝性技術可能會變得非常複雜。是以對于複雜的建立實體場景,可使用工廠。
User對象的構造函數被聲明為 protected。 Tenant實體即為User實體的工廠也是同一個子產品中唯一能夠通路User 構造器的類。這樣一來,隻有Tenant能夠建立User執行個體。
public class Tenant extends Entity {
// 該工廠簡化對User的建立,同時保證了Tenantld在User和Person對象中的正确性
// 該工廠能夠反映通用語言。
public User registerUser(String aUsername,
String aPassword,
Person aPerson) {
aPerson.setTenantld(this.tenantld());
User user = new User(this.tenantld(), aUsername, aPassword, aPerson);
return user;
}
參考
https://tech.meituan.com/2017/12/22/ddd-in-practice.html《實作領域驅動設計》
實體和值對象:從領域模型的基礎單元看系統設計
https://blog.csdn.net/Taobaojishu/article/details/106152641