典型的应用包含很多实体,一些实体的共有特征可以抽象为基类。有两种方法:
public interface IEntity{ }
第一种是引入接口,这种方式要求每个实体都有最基本的功能和ID属性。看起来不错,但使用接口作为基类通常不推荐:接口不能很好地表示实体之间的关系,实现接口意味着类拥有功能,它是”能做没事“,而不是”是某种对象“
两个实现相同接口的类,它们在垂直关系上没有关联。换句话说,接口代表实现类拥有某种功能,但领域实体需要的是类继承——属于某类的概念。实体不仅有相同功能,而且它们都是实体。因此可以使用抽象类构造:
package com.lugew.springbootddd;
public abstract class Entity {
protected long id;
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Entity)) {
return false;
}
Entity other = (Entity) obj;
if (this == other) // Reference equality
return true;
if (!this.getClass().equals(other.getClass()))
return false;
if (this.id == 0 || other.getId() == 0)
return false;
return this.id == other.getId(); //identifier equality
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
public long getId() {
return id;
}
protected void setId(long id) {
this.id = id;
}
}
抽象类拥有可继承的ID
,重写了equals
、hashCode
方法。我们为equals
方法增加了ID
相等验证。hashCode
方法确保两个相同id的对象返回的hashCode
是一样的。接下来我们重构SnackMachine
类:
package com.lugew.springbootddd.snackmachine;
import com.lugew.springbootddd.Entity;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public final class SnackMachine extends Entity {
private Money moneyInside;
private Money moneyInTransaction;
public void insertMoney(Money money) {
moneyInTransaction = Money.add(moneyInTransaction, money);
}
public void returnMoney() {
//moneyInTransaction = 0
}
public void buySnack() {
moneyInside = Money.add(moneyInside, moneyInTransaction);
//moneyInTransaction = 0
}
}
SnackMachine
类从基类继承了ID
属性和判断相等的方法。