域对象中的业务逻辑

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 的参数。

我认为将它们包含在 DataPointclass 中是有意义的,因为它们代表了 DataPeriod 必须知道的动作。

那个场景有某种模式吗?在并发方面提取或不提取这些方法有什么区别?

我认为如果这些方法只使用同一个 class 中的数据,或者换句话说,如果它们不依赖于其他模型,则最好将这些方法留在同一个模型 class 中classes.

当然,您永远不会从模型 class 访问服务,但有时很难决定模型 class 是否应该使用另一个模型 class。这取决于关系是否紧密(例如一个包含另一个,并且包含的​​ class 永远不会被独立使用)。如果两个模型 classes 没有很强的相关性,那么一个不应该管理另一个;在那种情况下,我会将工作留给第三个外部 class(例如服务或只是另一个模型 class 包含 其他)。

在您的情况下,DataPeriod 包含 dataPoints(可能是另一个模型 class),所以我认为将方法留在那里没问题。

这看起来像是使用动态属性的经典案例。
如果您有一个可以从其他属性计算然后将其声明为 动态 属性并为其编写自定义 属性处理程序

例如- 如果您有一个持久性属性(存储在数据库中的属性),例如出生日期 然后你可以声明一个 dynamic 属性 age 并在运行时计算它而不将它存储在数据库中。您将需要一个自定义 动态属性处理程序 ,例如 AgeAttributeHandler.java

拥有 动态属性 的另一个动机] 是 spring bean 约定,所有模型 bean 必须 仅具有 getterssetters业务逻辑 应该保存在模型 bean 之外。

在你的情况下,首先创建一个 DynamicAttributeHandler.java-

public interface DynamicAttributeHandler<VALUE, MODEL extends Object> {
    VALUE get(MODEL var1);

    void set(MODEL var1, VALUE var2);
}

然后,为 countdataPoints 创建 动态属性处理程序

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) {

    }
}

现在,只需 getterssetters.

即可创建模型
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);
    }
}