域对象中的业务逻辑
business logic in domain objects
有这个class:
public class DataPeriod {
private final String key;
private final LocalDate from;
private final LocalDate to;
private final Map<LocalDate, DataPoint> dataPoints = new HashMap<LocalDate, DataPoint>();
public DataPeriod(String key, LocalDate from, LocalDate to) {
this.key = key;
this.from = from;
this.to = to;
}
public LocalDate getFrom() {
return from;
}
public LocalDate getTo() {
return to;
}
public void hit(int id) {
DataPoint dataPoint = getOrCreate();
dataPoint.hit(id);
}
private DataPoint getOrCreate() {
LocalDate now = LocalDate.now();
String dataPointKey = key + now.toString();
if ( !dataPoints.containsKey(now) ) {
DataPoint dataPoint = new DataPoint(dataPointKey);
dataPoints.put(now, dataPoint);
}
return dataPoints.get(dataPointKey);
}
public long count() {
long count = 0l;
for (DataPoint dataPoint : dataPoints.values()) {
count += dataPoint.count();
}
return count;
}
将方法 hit(int id)
和 getOrCreate()
提取到其他 class 作为服务或助手可能是个好主意。但随后应修改它们以接收 DataPoint
的参数。
我认为将它们包含在 DataPoint
class 中是有意义的,因为它们代表了 DataPeriod
必须知道的动作。
那个场景有某种模式吗?在并发方面提取或不提取这些方法有什么区别?
我认为如果这些方法只使用同一个 class 中的数据,或者换句话说,如果它们不依赖于其他模型,则最好将这些方法留在同一个模型 class 中classes.
当然,您永远不会从模型 class 访问服务,但有时很难决定模型 class 是否应该使用另一个模型 class。这取决于关系是否紧密(例如一个包含另一个,并且包含的 class 永远不会被独立使用)。如果两个模型 classes 没有很强的相关性,那么一个不应该管理另一个;在那种情况下,我会将工作留给第三个外部 class(例如服务或只是另一个模型 class 包含 其他)。
在您的情况下,DataPeriod
包含 dataPoints
(可能是另一个模型 class),所以我认为将方法留在那里没问题。
这看起来像是使用动态属性的经典案例。
如果您有一个可以从其他属性计算然后将其声明为 动态 属性并为其编写自定义 属性处理程序 。
例如- 如果您有一个持久性属性(存储在数据库中的属性),例如出生日期 然后你可以声明一个 dynamic 属性 age 并在运行时计算它而不将它存储在数据库中。您将需要一个自定义 动态属性处理程序 ,例如 AgeAttributeHandler.java
。
拥有 动态属性 的另一个动机] 是 spring bean 约定,所有模型 bean 必须 仅具有 getters 和 setters。 业务逻辑 应该保存在模型 bean 之外。
在你的情况下,首先创建一个 DynamicAttributeHandler.java
-
public interface DynamicAttributeHandler<VALUE, MODEL extends Object> {
VALUE get(MODEL var1);
void set(MODEL var1, VALUE var2);
}
然后,为 count
和 dataPoints
创建 动态属性处理程序。
public class CountAttributeHandler implements DynamicAttributeHandler<Long, DatePeriod> {
@Override
public Long get(DatePeriod model) {
long count = 0l;
Map<LocalDate, DataPoint> dataPoints = model.getDataPoints();
for (DataPoint dataPoint : dataPoints.values()) {
count += dataPoint.count();
}
return count;
}
@Override
public void set(DatePeriod model, Long aLong) {
}
}
public class DataPointsAttributeHandler implements DynamicAttributeHandler<Map<LocalDate, DataPoint>, DatePeriod> {
@Override
public Map<LocalDate, DataPoint> get(DatePeriod model) {
LocalDate now = LocalDate.now();
String dataPointKey = model.getKey() + now.toString();
Map<LocalDate, DataPoint> dataPoints = model.getDataPoints();
if (!dataPoints.containsKey(now)) {
DataPoint dataPoint = new DataPoint(dataPointKey);
dataPoints.put(now, dataPoint);
}
return dataPoints;
}
@Override
public void set(DatePeriod model, Map<LocalDate, DataPoint> localDateDataPointMap) {
}
}
现在,只需 getters 和 setters.
即可创建模型
public class DatePeriod {
private final String key;
private final LocalDate from;
private final LocalDate to;
private final Map<LocalDate, DataPoint> dataPoints;
private final long count;
public DatePeriod(String key, LocalDate from, LocalDate to, Map<LocalDate, DataPoint> dataPoints, long count) {
this.key = key;
this.from = from;
this.to = to;
this.dataPoints = dataPoints;
this.count = count;
}
public LocalDate getFrom() {
return from;
}
public LocalDate getTo() {
return to;
}
public String getKey() {
return key;
}
public Map<LocalDate, DataPoint> getDataPoints() {
DynamicAttributeHandler<Map<LocalDate, DataPoint>, DatePeriod> dataPointsAttributeHandler = new DataPointsAttributeHandler();
return dataPointsAttributeHandler.get(this);
}
public long getCount() {
DynamicAttributeHandler<Long, DatePeriod> countAttributeHandler = new CountAttributeHandler();
return countAttributeHandler.get(this);
}
}
有这个class:
public class DataPeriod {
private final String key;
private final LocalDate from;
private final LocalDate to;
private final Map<LocalDate, DataPoint> dataPoints = new HashMap<LocalDate, DataPoint>();
public DataPeriod(String key, LocalDate from, LocalDate to) {
this.key = key;
this.from = from;
this.to = to;
}
public LocalDate getFrom() {
return from;
}
public LocalDate getTo() {
return to;
}
public void hit(int id) {
DataPoint dataPoint = getOrCreate();
dataPoint.hit(id);
}
private DataPoint getOrCreate() {
LocalDate now = LocalDate.now();
String dataPointKey = key + now.toString();
if ( !dataPoints.containsKey(now) ) {
DataPoint dataPoint = new DataPoint(dataPointKey);
dataPoints.put(now, dataPoint);
}
return dataPoints.get(dataPointKey);
}
public long count() {
long count = 0l;
for (DataPoint dataPoint : dataPoints.values()) {
count += dataPoint.count();
}
return count;
}
将方法 hit(int id)
和 getOrCreate()
提取到其他 class 作为服务或助手可能是个好主意。但随后应修改它们以接收 DataPoint
的参数。
我认为将它们包含在 DataPoint
class 中是有意义的,因为它们代表了 DataPeriod
必须知道的动作。
那个场景有某种模式吗?在并发方面提取或不提取这些方法有什么区别?
我认为如果这些方法只使用同一个 class 中的数据,或者换句话说,如果它们不依赖于其他模型,则最好将这些方法留在同一个模型 class 中classes.
当然,您永远不会从模型 class 访问服务,但有时很难决定模型 class 是否应该使用另一个模型 class。这取决于关系是否紧密(例如一个包含另一个,并且包含的 class 永远不会被独立使用)。如果两个模型 classes 没有很强的相关性,那么一个不应该管理另一个;在那种情况下,我会将工作留给第三个外部 class(例如服务或只是另一个模型 class 包含 其他)。
在您的情况下,DataPeriod
包含 dataPoints
(可能是另一个模型 class),所以我认为将方法留在那里没问题。
这看起来像是使用动态属性的经典案例。
如果您有一个可以从其他属性计算然后将其声明为 动态 属性并为其编写自定义 属性处理程序 。
例如- 如果您有一个持久性属性(存储在数据库中的属性),例如出生日期 然后你可以声明一个 dynamic 属性 age 并在运行时计算它而不将它存储在数据库中。您将需要一个自定义 动态属性处理程序 ,例如 AgeAttributeHandler.java
。
拥有 动态属性 的另一个动机] 是 spring bean 约定,所有模型 bean 必须 仅具有 getters 和 setters。 业务逻辑 应该保存在模型 bean 之外。
在你的情况下,首先创建一个 DynamicAttributeHandler.java
-
public interface DynamicAttributeHandler<VALUE, MODEL extends Object> {
VALUE get(MODEL var1);
void set(MODEL var1, VALUE var2);
}
然后,为 count
和 dataPoints
创建 动态属性处理程序。
public class CountAttributeHandler implements DynamicAttributeHandler<Long, DatePeriod> {
@Override
public Long get(DatePeriod model) {
long count = 0l;
Map<LocalDate, DataPoint> dataPoints = model.getDataPoints();
for (DataPoint dataPoint : dataPoints.values()) {
count += dataPoint.count();
}
return count;
}
@Override
public void set(DatePeriod model, Long aLong) {
}
}
public class DataPointsAttributeHandler implements DynamicAttributeHandler<Map<LocalDate, DataPoint>, DatePeriod> {
@Override
public Map<LocalDate, DataPoint> get(DatePeriod model) {
LocalDate now = LocalDate.now();
String dataPointKey = model.getKey() + now.toString();
Map<LocalDate, DataPoint> dataPoints = model.getDataPoints();
if (!dataPoints.containsKey(now)) {
DataPoint dataPoint = new DataPoint(dataPointKey);
dataPoints.put(now, dataPoint);
}
return dataPoints;
}
@Override
public void set(DatePeriod model, Map<LocalDate, DataPoint> localDateDataPointMap) {
}
}
现在,只需 getters 和 setters.
即可创建模型public class DatePeriod {
private final String key;
private final LocalDate from;
private final LocalDate to;
private final Map<LocalDate, DataPoint> dataPoints;
private final long count;
public DatePeriod(String key, LocalDate from, LocalDate to, Map<LocalDate, DataPoint> dataPoints, long count) {
this.key = key;
this.from = from;
this.to = to;
this.dataPoints = dataPoints;
this.count = count;
}
public LocalDate getFrom() {
return from;
}
public LocalDate getTo() {
return to;
}
public String getKey() {
return key;
}
public Map<LocalDate, DataPoint> getDataPoints() {
DynamicAttributeHandler<Map<LocalDate, DataPoint>, DatePeriod> dataPointsAttributeHandler = new DataPointsAttributeHandler();
return dataPointsAttributeHandler.get(this);
}
public long getCount() {
DynamicAttributeHandler<Long, DatePeriod> countAttributeHandler = new CountAttributeHandler();
return countAttributeHandler.get(this);
}
}