换一种方式创建对象

我有一个类。如下:

@Data
public class UserValidateLog extends  BaseLog{

    private String changedField;

    private String value;

    private int validate;

    private int result;

    private String userName;

    private Long uid;
}

这个类用来记录用户发送验证码和校验验证码的日志。但是在不同的场景会使用到这个类不同的字段,如
场景1:用户忘记密码,发送验证码时,会使用changedField、value、validate、userName字段
场景2:用户登录系统后更改绑定邮箱,发送验证码时,会使用changedField、value、validate、userName、uid字段
场景3:用户忘记密码,校验验证码时,会使用changedField、validate、userName、result字段。



所以,如果给UserValidateLog实例赋予值成了一个问题,当然,最简单的是:

        UserValidateLog log = new UserValidateLog();
        log.setValidate(1);
        log.setResult(1);
        log.setUserName("YYFYY");

但是我觉得这不够优雅,因为我会在很多地方使用到这个对象,所以我想把参数的设置放入构造函数,那我需要创建这些构造函数:

    public UserValidateLog(){

    }

    public UserValidateLog(String changedField,String value,Long uid){
        this.changedField = changedField;
        this.value = value;
        this.setUid(uid);
    }

    public UserValidateLog(String changedField,String value,String userName){
        this.changedField = changedField;
        this.value = value;
        this.userName = userName;
    }

    public UserValidateLog(String changedField,String value,int result,String userName){
        this.changedField = changedField;
        this.value = value;
        this.result = result;
        this.userName = userName;
    }

    public UserValidateLog(String changedField,String value,int result,String userName,int validate){
        this.changedField = changedField;
        this.value = value;
        this.result = result;
        this.userName = userName;
        this.validate = validate;
    }

    public UserValidateLog(String changedField,String value,int result,String userName,Long uid){
        this.changedField = changedField;
        this.value = value;
        this.result = result;
        this.userName = userName;
        this.setUid(uid);
    }

    public UserValidateLog(String changedField,String value,int result,String userName,Long uid,int validate){
        this.changedField = changedField;
        this.value = value;
        this.result = result;
        this.userName = userName;
        this.setUid(uid);
        this.validate = validate;
    }

    public UserValidateLog(String changedField,String value,String userName,Long uid){
        this.changedField = changedField;
        this.value = value;
        this.userName = userName;
        this.setUid(uid);
    }

    public UserValidateLog(String changedField,String value,String userName,Long uid,int validate){
        this.changedField = changedField;
        this.value = value;
        this.userName = userName;
        this.setUid(uid);
        this.validate = validate;
    }

这样在使用的时候我只需要使用合适的构造函数构造就行了,比如这样:

logRecordService.recordLog(new UserValidateLog(validateType.name(),code,username,uid));

但是这样也有问题,写构造函数太麻烦了,并且容易不知道使用哪个构造函数,所以我们可以让每个set方法返回当前this对象,简写一下可以直接使用@Accessors注解,如下:

@Data
@Accessors(chain = true)
public class UserValidateLog extends  BaseLog{

    private String changedField;

    private String value;

    private int validate;

    private int result;

    private String userName;
}

@Accessors(chain = true)的chain属性,不写默认为false,当该值为 true 时,对应字段的 setter 方法调用后,会返回当前对象。
那么我们在创建对象的时候就可以这样:

        logRecordService.recordLog(new UserValidateLog()
                .setChangedField(validateType.name())
                .setValue(code)
                .setUserName(username)
                .setUid(from));

需要哪些参数可以自由组装(类似于构造者模式),这样就不需要创建各种构造方法了。
如果有场景需要保证对象的属性在创建后就不可变,Effective Java有一种做法,首先,对象的参数应该是不可变,如下:

@Data
@Accessors(chain = true)
public class UserValidateLog extends  BaseLog{

    private final String changedField;

    private final String value;

    private final int validate;

    private final int result;

    private final String userName;
}

那么如何在创建的时候设置参数呢,如下:

@Data
@Accessors(chain = true)
public class UserValidateLog extends  BaseLog{
    
    private final String changedField;

    private final String value;

    private final int validate;

    private final int result;

    private final String userName;

    @Accessors(fluent = true,chain = true)
    @Data
    public class Builder{
        private  String changedField;

        private  String value;

        private  int validate;

        private  int result;

        private  String userName;
        
        public UserValidateLog build(){
            return new UserValidateLog(this);
        }
    }
    
    private UserValidateLog(Builder builder){
        this.changedField = builder.changedField;
        this.validate = builder.validate;
        this.value = builder.value;
        this.result = builder.result;
        this.userName = builder.userName;
    }
    
    //获取对象示例
    public void getUserValidateLog(){
        UserValidateLog log =new UserValidateLog.Builder().changedField("11").validate(1).value("33").build();
    }
}
posted @ 2023-03-17 17:05  丶阳凡  阅读(29)  评论(0)    收藏  举报