多个构造器时考虑用构建器:javaBeans模式可能处于不一致性

今天观看《Effective Java 3》的第二条:遇到多个构造器参数时考虑用构建器

有这样一段话:

=============

遗憾的是,JavaBeans模式自身有着严重的缺点。

因为构造过程被分到了几个调用中,在构造过程中JavaBeans可能处于不一致的状态。

类无法仅仅通过检验构造器参数的有效性来保证一致。

试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来非常困难。

于此相关的另一点不足在于,JavaBeans模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力来确保它的线程安全。

=============

1. 重叠构造

在java中比较基础的是构造器来初始化,作为程序员习惯使用重叠构造模式,当传入一个参数的构造时候,第一个有一个必选参数,第二个有一个必选参数和一个可选参数,第三个有两个可选参数….通过重叠构造,关联所有的多参构造,实现关联;如下代码:但是有一个问题,一个参数,两个参数,三个参数,使用其构造传参会比较明确,但是对于多参的构造,会涉及到参数顺序的问题,有时候会传参出错,而且参数太多,难以阅读,对参数的把控性不高,不利于程序的阅读。

2. javabeans 模式

出于程序可读性以及参数的可控性的考虑我们会是会用javabean来进行类实例化和属性的赋值:

在使用javabean的时候,尤其是多线程时候,获取同一个javabean(可以通过序列/反序列获取),那么下面模拟一个场景:

线程A: 获取person,对其name age sex 就行set操作

同样线程B: 获取person,对其进行get操作

这时候会出现一种情况,在线程A中没有set完毕,线程B 就开始取相应的属性

那么就会造成javabean出于不一致的状态;随之相关就是线程安全的问题,所以javabean作为数据的一个填充,姚进行必要的保护性拷贝(这里不做解释)

在建造者模式中,提供一个辅助的静态建造器builder,可以在里面set 的属性,与javaBean不同的是,建造者是先set,在通过build实例化类,这样既可以提高代码的阅读性,也可以防止对象没有实例化,就被调用;不会造成不一致性,同时解决了javabean模式的线程安全问题。

package com.example.builder.demo;

public class ParamsBuilder1 {
	//必要参数
    private String password ;
    private String username = null;
    //可选参数
	private String url;
	private String address;
	
	public String getUsername() {
		return username;
	}
	public String getPassword() {
		return password;
	}
	public String getUrl() {
		return url;
	}
	
	public static class Builder{
		//必要参数
        private String password ;
        private String username = null;
        //可选参数
    	private String url;
    	private String address;
    	//如果存在必选参数,则用有参构造器
    	public Builder(String username,String password) {
    		this.username=username;
    		this.password=password;
    	}
    
    	public Builder() {
    		
    	}
    	
        public Builder url(String url) {
        	this.url=url;
        	return this;
        }
        
        public Builder address(String address) {
        	this.address=address;
        	return this;
        }
        
        public ParamsBuilder1 build() {
        	return new ParamsBuilder1(this);
        }
	}
	
	 private ParamsBuilder1(Builder b) {
         url = b.url;
         password = b.password;
         username = b.username;
         address=b.address;
     }
	 
	@Override
	public String toString() {
		return "ParamsBuilder [password=" + password + ", username=" + username + ", url=" + url + ", address="
				+ address + "]";
	}
	public static void main(String[] args) {
		ParamsBuilder1 pb1=new ParamsBuilder1.Builder("root", "123").address("中国").url("www.baidu.com").build();
		System.out.println("有参构造方法:"+pb1.toString());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值