如何进行不同类型的对象状态验证
How to do different types of object state validation
我需要从一个或两个不同的数据源向调用者提供记录,并且在指定的日期范围或年份范围内。
我的困境是我应该使用重载方法还是具有状态验证逻辑的 Request 对象。
所以要么:
public List<Record> getRecords (Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired)
public List<Record> getRecords (int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired)
或类似这样的内容:
public List<Record> getRecords(Request request)
请求看起来像这样:
public class Request{
private final Date fromDate;
private final Date toDate;
private final int fromYear;
private final int toYear;
private final boolean dataSourceARequired;
private final boolean dataSourceBRequired;
public Request(Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired){
if (fromDate == null) {
throw new IllegalArgumentException("fromDate can't be null");
}
if (toDate == null) {
throw new IllegalArgumentException("toDate can't be null");
}
if (!dataSourceARequired && !dataSourceBRequired){
throw new IllegalStateException ("No data source requested");
}
if (fromDate.after(toDate)){
throw new IllegalStateException ("startDate can't be after endDate");
}
this.fromDate = fromDate;
this.toDate = toDate;
this.dataSourceARequired = dataSourceARequired;
this.dataSourceBRequired = dataSourceBRequired;
this.fromYear = -1;
this.toYear = -1;
}
public Request(int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired){
if (fromYear > toYear) {
throw new IllegalArgumentException("fromYear can't be greater than toYear");
}
if (!dataSourceARequired && !dataSourceBRequired){
throw new IllegalStateException ("No data source requested");
}
this.dataSourceARequired = dataSourceARequired;
this.dataSourceBRequired = dataSourceBRequired;
this.fromYear = fromYear;
this.toYear = toYear;
this.fromDate = null;
this.toDate = null;
}
}
或者有别的方法吗?
你不应该使用第二种情况,因为它违反了每个 class 应该有一个 well-defined 责任的规则。在这里,您的 class 负责详细日期范围和年份日期范围。如果您添加更多条件,这个 class 会变得很可怕。
所以你可以使用第一种方法,而且很多人都这样做。
如果您想创建 classes 来封装请求数据,您应该创建一个基础抽象 class 或接口,然后为每种类型创建不同类型的请求子class您可以使用的标准。例如:
public interface Request {
execute();
}
public class YearRangeRequest implements Request {
int fromYear;
int toYear;
public execute();
... etc
另一种解决方案:使用带有两个构造函数的 DateRange
class:
public class DateRange {
final Date start;
final Date end;
public DateRange(Date start, Date end) {
this.start = start;
this.end = end;
}
public DateRange(int startYear, int endYear) {
this(yearBegining(startYear), yearBegining(endYear));
}
...
}
我需要从一个或两个不同的数据源向调用者提供记录,并且在指定的日期范围或年份范围内。
我的困境是我应该使用重载方法还是具有状态验证逻辑的 Request 对象。
所以要么:
public List<Record> getRecords (Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired)
public List<Record> getRecords (int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired)
或类似这样的内容:
public List<Record> getRecords(Request request)
请求看起来像这样:
public class Request{
private final Date fromDate;
private final Date toDate;
private final int fromYear;
private final int toYear;
private final boolean dataSourceARequired;
private final boolean dataSourceBRequired;
public Request(Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired){
if (fromDate == null) {
throw new IllegalArgumentException("fromDate can't be null");
}
if (toDate == null) {
throw new IllegalArgumentException("toDate can't be null");
}
if (!dataSourceARequired && !dataSourceBRequired){
throw new IllegalStateException ("No data source requested");
}
if (fromDate.after(toDate)){
throw new IllegalStateException ("startDate can't be after endDate");
}
this.fromDate = fromDate;
this.toDate = toDate;
this.dataSourceARequired = dataSourceARequired;
this.dataSourceBRequired = dataSourceBRequired;
this.fromYear = -1;
this.toYear = -1;
}
public Request(int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired){
if (fromYear > toYear) {
throw new IllegalArgumentException("fromYear can't be greater than toYear");
}
if (!dataSourceARequired && !dataSourceBRequired){
throw new IllegalStateException ("No data source requested");
}
this.dataSourceARequired = dataSourceARequired;
this.dataSourceBRequired = dataSourceBRequired;
this.fromYear = fromYear;
this.toYear = toYear;
this.fromDate = null;
this.toDate = null;
}
}
或者有别的方法吗?
你不应该使用第二种情况,因为它违反了每个 class 应该有一个 well-defined 责任的规则。在这里,您的 class 负责详细日期范围和年份日期范围。如果您添加更多条件,这个 class 会变得很可怕。
所以你可以使用第一种方法,而且很多人都这样做。
如果您想创建 classes 来封装请求数据,您应该创建一个基础抽象 class 或接口,然后为每种类型创建不同类型的请求子class您可以使用的标准。例如:
public interface Request {
execute();
}
public class YearRangeRequest implements Request {
int fromYear;
int toYear;
public execute();
... etc
另一种解决方案:使用带有两个构造函数的 DateRange
class:
public class DateRange {
final Date start;
final Date end;
public DateRange(Date start, Date end) {
this.start = start;
this.end = end;
}
public DateRange(int startYear, int endYear) {
this(yearBegining(startYear), yearBegining(endYear));
}
...
}