典型的应用包含很多实体,一些实体的共有特征可以抽象为基类。有两种方法:
public interface IEntity{ }
第一种是引入接口,这种方式要求每个实体都有最基本的功能和ID属性。看起来不错,但使用接口作为基类通常不推荐:接口不能很好地表示实体之间的关系,实现接口意味着类拥有功能,它是”能做没事“,而不是”是某种对象“
两个实现相同接口的类,它们在垂直关系上没有关联。换句话说,接口代表实现类拥有某种功能,但领域实体需要的是类继承——属于某类的概念。实体不仅有相同功能,而且它们都是实体。因此可以使用抽象类构造:
package com.lugew.springbootddd;public abstract class Entity {protected long id;@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Entity)) {return false;}Entity other = (Entity) obj;if (this == other) // Reference equalityreturn 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}@Overridepublic 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@Setterpublic 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属性和判断相等的方法。
