在《代码整洁之道》中,方法参数是禁止超过3个的,《代码整洁之道》提倡把超过3个参数的封装到类中.
我们一般在构造一个javaBean 对象时,无非以下几种写法:
1. 采用Javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值
/**
* @author Tonfu.Chia
*/
public class Person {
private int id;
private String name;
private int age;
private String sex;
private String phone;
private String address;
private String desc;
public Person() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
- 各种构造函数 有参 无参
/**
* @author Tonfu.Chia
*/
public class Person {
private int id;
private String name;
private int age;
private String sex;
private String phone;
private String address;
private String desc;
public Person() {
}
public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.phone = phone;
this.address = address;
this.desc = desc;
}
public Person(int id, String name, int age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
}
- 重叠构造器模式
/**
* @author Tonfu.Chia
*/
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;
public Person(int id, String name) {
this(id, name, 0);
}
public Person(int id, String name, int age) {
this(id, name, age, "");
}
public Person(int id, String name, int age, String sex) {
this(id, name, age, sex, "");
}
public Person(int id, String name, int age, String sex, String phone) {
this(id, name, age, sex, phone, "");
}
public Person(int id, String name, int age, String sex, String phone, String address) {
this(id, name, age, sex, phone, address, "");
}
public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.phone = phone;
this.address = address;
this.desc = desc;
}
}
比较
构造方式 | 优点 | 缺点 |
---|---|---|
JavaBean | 创建灵活,代码易可读 | 构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。 |
构造函数 | 每种初始化都可以对应单独方法 | 属性过多的话会让构造函数十分臃肿,而且不能灵活的选择只设置某些参数,添加参数需要添加对应构造方法。 |
重叠构造器 | 比构造函数灵活,参数少时可以使用 | 如果参数比较多时,类里面会出现一堆构造方法,并且阅读困难,很容易就把两个属性参数写颠倒位置了,编译不会出错,但运行就会出错了 |
更高效的构造方式–构建器
在《Effective Java第2版》第二章创建和销毁对象 中有提到,
遇到多个构造器参数时要考虑使用构建器(Builder模式)
使用Builder模式的步骤:
1. 不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个build对象。
2. 然后让客户端在build对象上调用类似的setter方法来设置每个相关的可选参数,
3. 最后,客户端调用无参的build方法来生成不可变的对象。这个builder是它构建的静态成员类。
package com.ampmind.common.model.swagger;
/**
* @author Tonfu.Chia
*/
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;
private Person(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
this.sex = builder.sex;
this.phone = builder.phone;
this.address = builder.address;
this.desc = builder.desc;
}
public static class Builder {
//必要参数
private final int id;
private final String name;
//可选参数
private int age;
private String sex;
private String phone;
private String address;
private String desc;
public Builder(int id, String name) {
this.id = id;
this.name = name;
}
public Builder age(int val) {
this.age = val;
return this;
}
public Builder sex(String val) {
this.sex = val;
return this;
}
public Builder phone(String val) {
this.phone = val;
return this;
}
public Builder address(String val) {
this.address = val;
return this;
}
public Builder desc(String val) {
this.desc = val;
return this;
}
public Person build() {
return new Person(this);
}
}
}
Person是不可变的,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身。以便可以把连接起来。下面是客户端使用代码:
public class Test {
public static void main(String[] args) {
Person person = new Person.Builder(1, "张三")
.age(18).sex("男").desc("测试使用Builder模式").build();
System.out.println(person.toString());
}
}
Lombok - @Builder
/**
* @author Tonfu.Chia
*/
@Builder
@Getter
@RequiredArgsConstructor
public class Person {
//必要参数
@NonNull
private final int id;
@NonNull
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;
}
使用如下 :
Person person= Person.builder().id(1).name("张三").age(22).sex("男").build();
实际使用情况
- 是不是可以不用Setter,而使用Builder,哪些地方会遇到问题?
- Mybatis 可以给没有set的bean赋值?
- lombok 不支持Builder设置有参构造器?