我想问您关于为以下要求设计最佳验证方法的想法:
我们有一个User
模型类,根据它的状态,我们可以更新一些特定的字段。如您所见,模型类的可更改性取决于其状态字段。
ACTIVE
,则所有字段(名称,姓氏,
密码....)可以更新。INACTIVE
,则只能更新密码。BLOCKED
,则名称和姓氏可以是
已更新。DELETED
,则更新操作不是
允许用于任何字段。很明显,可以简单地通过添加一个UserValidator
类来完成,并且在设置方法中设置值之前,我可以调用UserValidator
来检查是否允许该操作。但是,它有一个缺点(?):如果将有一个新字段(假设为maritalStatus
)并且添加该字段的开发人员忘记设置UserValidator
之前调用maritalStatus
,会发生什么?
我能想到的其他解决此问题的方法:
CustomValidator
使用自定义注释。但是,
因为注释不能知道对象的先前值而无法使用。
我的意思是isValid()
的{{1}}方法不会知道名称
字段是否更改(它是“ John”,现在开发人员想要更改它)
到“杰克”)我已经看到装饰器模式可以用于此问题,但我不知道如何使用。我认为验证模型类超出装饰设计的责任。
CustomValidator
答案 0 :(得分:1)
我建议您使用意图揭示界面,而不要使用setter / getter
例如
public class User {
private Integer id;
private String name;
private String surname;
private String password;
private Status status;
void rename(String newName, String newSurname){
if(Status.INACTIVE.equals(status) || Status.DELETED.equals(status))
throws new Exception("You cannot rename a inactive or deleted user");
this.name = newName;
this.surname = newSurname;
}
.....
}
答案 1 :(得分:0)
这是我将使用的方法。如果你们也可以投票支持,那就太好了。
基本上,我将使用装饰器模式。
public interface User {
Integer getId();
void setId(Integer id);
String getName();
void setName(String name);
String getSurname();
void setSurname(String surname);
String getPassword();
void setPassword(String password);
Status getStatus();
void setStatus(Status status);
}
public class UserImpl implements User {
private Integer id;
private String name;
private String surname;
private String password;
private Status status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
public abstract class UserDecorator implements User{
private final User user;
public UserDecorator(User user) {
this.user = user;
}
public Integer getId() {
return user.getId();
}
public void setId(Integer id) {
user.setId(id);
}
public String getName() {
return user.getName();
}
public void setName(String name) {
user.setName(name);
}
public String getSurname() {
return user.getSurname();
}
public void setSurname(String surname) {
user.setSurname(surname);
}
public String getPassword() {
return user.getPassword();
}
public void setPassword(String password) {
user.setPassword(password);
}
public Status getStatus() {
return user.getStatus();
}
public void setStatus(Status status) {
user.setStatus(status);
}
}
无效用户:
public class InactiveUserImpl extends UserDecorator {
public InactiveUserImpl(User user) {
super(user);
}
// didn't override setPassword therefore that field can be updated when the status of user is Inactive
@Override
public void setId(Integer id) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
@Override
public void setName(String name) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
@Override
public void setSurname(String surname) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
@Override
public void setStatus(Status status) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
}
活动用户:
public class ActiveUserImpl extends UserDecorator {
public ActiveUserImpl(User user) {
super(user);
}
// not overriding any method hence everything can be updated
}
基本上,无论谁要求UserImpl,我都将退回给他包装的UserImpl版本,例如
class UserRepository{
public User getById(String id){
User user=db.getUserById(id);
// this can be done with Enum but it is out of our scope
if (user.getStatus().equals(INACTIVE))
return new InactiveUserImpl(user);
// ....
return null;
}
}
如果您这样做:
User user= userRepository.getById(1)
然后,您将获得带有允许的设置器集的用户。