在setter方法中验证模型类

时间:2019-05-03 09:36:28

标签: java design-patterns

我想问您关于为以下要求设计最佳验证方法的想法:

我们有一个User模型类,根据它的状态,我们可以更新一些特定的字段。如您所见,模型类的可更改性取决于其状态字段。

  • 如果用户的状态为ACTIVE,则所有字段(名称,姓氏, 密码....)可以更新。
  • 如果用户的状态为INACTIVE,则只能更新密码。
  • 如果用户的状态为BLOCKED,则名称和姓氏可以是 已更新。
  • 如果用户的状态为DELETED,则更新操作不是 允许用于任何字段。

很明显,可以简单地通过添加一个UserValidator类来完成,并且在设置方法中设置值之前,我可以调用UserValidator来检查是否允许该操作。但是,它有一个缺点(?):如果将有一个新字段(假设为maritalStatus)并且添加该字段的开发人员忘记设置UserValidator之前调用maritalStatus,会发生什么?

我能想到的其他解决此问题的方法:

  1. 通过扩展CustomValidator使用自定义注释。但是, 因为注释不能知道对象的先前值而无法使用。 我的意思是isValid()的{​​{1}}方法不会知道名称 字段是否更改(它是“ John”,现在开发人员想要更改它) 到“杰克”)
  2. 代理模式可能有用,但不确定是否使用它是个好主意 模型对象的代理。

我已经看到装饰器模式可以用于此问题,但我不知道如何使用。我认为验证模型类超出装饰设计的责任。

CustomValidator

2 个答案:

答案 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) 

然后,您将获得带有允许的设置器集的用户。