如何在java中处理模型验证和一致性检查
我的问题最好用一些代码来说明。请浏览代码并阅读最后的问题。
enum PropertySourceEnum {
DEFAULT,
CALCULATED,
USER,
UNKNOWN
}
enum PropertyValidityEnum {
ERROR,
WARNING,
OK
}
class WorkerProperty <T>{
private T value;
private PropertyValidity validity;
private PropertySourceEnum source;
public WorkerProperty(T value) {
this.value = value;
this.source = PropertySourceEnum.UNKNOWN;
this.validity = new PropertyValidity(PropertyValidityEnum.WARNING,
"Unverified");
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public PropertySourceEnum getSource() {
return this.source;
}
public void setSource(PropertySourceEnum source) {
this.source = source;
}
public PropertyValidity getValidity() {
return this.validity;
}
public void setValidity(PropertyValidity validity) {
this.validity = validity;
}
}
class PropertyValidity {
private final PropertyValidityEnum state;
private final String message;
public PropertyValidity(PropertyValidityEnum state,
String message) {
this.state = state;
this.message = message;
}
}
class DefaultingService {
// Using reflection iterate through all the properties
// and if property source is UNKNOWN or was previous DEFAULTED
// then see if the database has an appropriate value for it
// set it to that value and set its source to "DEFAULTED"
}
interface Rule {
public void fire(Worker w);
}
class ValidationWorkerAge implements Rule {
@Override
public void fire(Worker w) {
// is the worker's age > 16 < 85
// if age is not set set the validity to ERROR, "required field"
int age = (int) w.age.value;
if (age <= 16) {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
"Worker too young");
w.age.setValidity(pv);
} else if (age > 75) {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
"Worker too old");
w.age.setValidity(pv);
} else {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.OK,
"OK");
w.age.setValidity(pv);
}
}
}
class ValidationService {
// Has a Tree of validation rules and traverses the tree fire()ing each rule
// along the way
}
class CheckWorkerAgeConsistency implements Rule {
@Override
public void fire(Worker w) {
// if both age and dateOfBirth are set
// Check that worker age = today().year - dateofBirth.years()
// or dateofBirth.years() = today().year - age
// if only DateOfBith is set then calculate age and mark its source as CALCULATED
// if only age is set then calculate DateOfBith and mark its source as CALCULATED
// if neither is set do nothing
}
}
class ConsistencyService {
// Has a Tree of consistency rules and traverses the tree fire()ing each rule
// along the way
}
// ---------------------- // Worker 实现
class Worker1 {
WorkerProperty<Long> id;
WorkerProperty<String> name;
WorkerProperty<String> surname;
WorkerProperty<Integer> dateOfBirth;
WorkerProperty<Integer> age;
}
class Manager1 extends Worker1 {
}
// plus other types of worker
// ---------------------- // 替代 Worker 实现
class Worker2 {
Long id;
PropertyValidity id_validity;
PropertySourceEnum id_source;
String name;
PropertyValidity name_validity;
PropertySourceEnum name_source;
String surname;
PropertyValidity surname_validity;
PropertySourceEnum surname_source;
Integer dateOfBirth;
PropertyValidity dateOfBirth_validity;
PropertySourceEnum dateOfBirth_source;
Integer age;
PropertyValidity age_validity;
PropertySourceEnum age_source;
}
class Manager2 extends Worker2 {
}
// plus other types of worker
我的问题是:
综上所述,Worker应该如何实现。我应该按照 Worker1 类中所示的方式实现 Worker,还是应该按照 Worker2 类中所示的方式实现 Worker?
感谢和亲切的问候
My question is best illustrated with some code. Please browse through the code and read the question at the end.
enum PropertySourceEnum {
DEFAULT,
CALCULATED,
USER,
UNKNOWN
}
enum PropertyValidityEnum {
ERROR,
WARNING,
OK
}
class WorkerProperty <T>{
private T value;
private PropertyValidity validity;
private PropertySourceEnum source;
public WorkerProperty(T value) {
this.value = value;
this.source = PropertySourceEnum.UNKNOWN;
this.validity = new PropertyValidity(PropertyValidityEnum.WARNING,
"Unverified");
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public PropertySourceEnum getSource() {
return this.source;
}
public void setSource(PropertySourceEnum source) {
this.source = source;
}
public PropertyValidity getValidity() {
return this.validity;
}
public void setValidity(PropertyValidity validity) {
this.validity = validity;
}
}
class PropertyValidity {
private final PropertyValidityEnum state;
private final String message;
public PropertyValidity(PropertyValidityEnum state,
String message) {
this.state = state;
this.message = message;
}
}
class DefaultingService {
// Using reflection iterate through all the properties
// and if property source is UNKNOWN or was previous DEFAULTED
// then see if the database has an appropriate value for it
// set it to that value and set its source to "DEFAULTED"
}
interface Rule {
public void fire(Worker w);
}
class ValidationWorkerAge implements Rule {
@Override
public void fire(Worker w) {
// is the worker's age > 16 < 85
// if age is not set set the validity to ERROR, "required field"
int age = (int) w.age.value;
if (age <= 16) {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
"Worker too young");
w.age.setValidity(pv);
} else if (age > 75) {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
"Worker too old");
w.age.setValidity(pv);
} else {
PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.OK,
"OK");
w.age.setValidity(pv);
}
}
}
class ValidationService {
// Has a Tree of validation rules and traverses the tree fire()ing each rule
// along the way
}
class CheckWorkerAgeConsistency implements Rule {
@Override
public void fire(Worker w) {
// if both age and dateOfBirth are set
// Check that worker age = today().year - dateofBirth.years()
// or dateofBirth.years() = today().year - age
// if only DateOfBith is set then calculate age and mark its source as CALCULATED
// if only age is set then calculate DateOfBith and mark its source as CALCULATED
// if neither is set do nothing
}
}
class ConsistencyService {
// Has a Tree of consistency rules and traverses the tree fire()ing each rule
// along the way
}
// ----------------------
// Worker Implementation
class Worker1 {
WorkerProperty<Long> id;
WorkerProperty<String> name;
WorkerProperty<String> surname;
WorkerProperty<Integer> dateOfBirth;
WorkerProperty<Integer> age;
}
class Manager1 extends Worker1 {
}
// plus other types of worker
// ----------------------
// Alternative Worker implementation
class Worker2 {
Long id;
PropertyValidity id_validity;
PropertySourceEnum id_source;
String name;
PropertyValidity name_validity;
PropertySourceEnum name_source;
String surname;
PropertyValidity surname_validity;
PropertySourceEnum surname_source;
Integer dateOfBirth;
PropertyValidity dateOfBirth_validity;
PropertySourceEnum dateOfBirth_source;
Integer age;
PropertyValidity age_validity;
PropertySourceEnum age_source;
}
class Manager2 extends Worker2 {
}
// plus other types of worker
My question is:
Given the above, how should Worker be implemented. Should I implement Worker as shown in the class Worker1 or Should I implement Worker as shown in Worker2?
Thanks and kind regards
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能需要考虑使用 JSR 303 Bean Validation 进行验证。 Hibernate Validator 是其中的一种实现。
当然,使用 JSR 303 中的一些想法会很好,例如,您可以考虑使用注释来代替 Worker1 中的 WorkerProperty 容器或 Worker2 中的 PropertyValidity 。
You may want to consider using JSR 303 Bean Validation for validation. Hibernate Validator is one implementation of this.
Certainly using some ideas from JSR 303 would be good e.g. instead of the WorkerProperty container in Worker1 or PropertyValidity in Worker2, you could consider using Annotations instead.