在实例化一个类的过程中,通常会遇到多个参数的构造函数,但如果有些参数是非必需的呢?每次都要初始化那么多参数么?
public class Person {
private int id;//身份证号
private String name;//姓名
private int age;//年龄
private boolean sex;//性别
private String desc;//个人描述
public Person(int id, String name, int age, boolean sex, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.desc = desc;
}
}
或者像下面这样,创建一个必选参数的构造器,在创建几个可选参数的构造器?重叠构造器模式
public Person(int id, String name) {//两个参数的
this.id = id;
this.name = name;
}
public Person(int id, String name, int age) {//三个参数的
this.id = id;
this.name = name;
this.age = age;
}
public Person(int id, String name, int age, boolean sex) {//四个参数的
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
- 形式:先提供一个包含了所有的构造参数的构造方法,再被其余的构造参数较少的构造方法来调用。简单的说,就是最终会调用到全参构造方法。
- 好处:可降低调用者的接入成本,通常调用者都喜欢构造器的参数越少越好,通过重叠构造器模式就可以达到这种目的。
- 坏处:当构造器参数较多时,就会出现很多个构造方法,造成代码臃肿;当构造器参数是同一类型时,如果参数没有对号入座,编译时类型检查通过了,但是到了程序运行时才出错。
或setter方法?JavaBeans模式
- 定义:遵循特定规则的java类,即必须有一个无参的构造函数、属性必须私有化、私有化的属性必须通过公有类型的方法(get/set)对外暴露。
- 好处:创建实例成本较低,代码实现也比较直观,即需要什么参数就指定什么参数。
- 坏处:对象实例的构造过程被其属性的set方法所分离,难以保证线程安全;对外暴露了修改属性的途径(即set方法),对象的不可变性难以保证,即存在风险入侵口。
JavaBean模式自身有严重的缺点,因为构造过程被分到几个调用中,在构造过程中Javabean可能处于不一致的状态,类无法仅仅通过检验构造器参数的有效性来保证一致性。JavaBean模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力确保线程安全 ---摘自Effective Java
那么我们该怎样用构建器来实现类的实例化而又不受制于构造函数限制呢?构建器模式
public class Person {
private final int id;//身份证号
private final String name;//姓名
private int age;//年龄
private boolean sex;//性别
private String desc;//个人描述
private Person(Builder builder){
this.id=builder.id;
this.name=builder.name;
this.age=builder.age;
this.sex=builder.sex;
this.desc=builder.desc;
}
public static class Builder{
private final int id;
private final String name;
private int age;
private boolean sex;
private String desc;
public Builder(int id, String name) {
this.id = id;
this.name = name;
}
public Builder age(int age){
//年龄合法性检查
if(age<0)throw new IllegalArgumentException();
else this.age=age;
return this;
}
public Builder sex(boolean sex){
this.sex=sex;
return this;
}
public Builder desc(String desc){
this.desc=desc;
return this;
}
public Person build(){
return new Person(this);
}
}
@Override
public String toString() {
return "id:"+this.id+" 姓名:"+this.name+" 年龄:"+this.age+" 性别:"+this.sex+" 描述:"+this.desc;
}
}
在main函数中测试一下
public static void main(String[] args) {
Builder builder=new Person.Builder(123,"张三");
Person person=builder.age(18).sex(false).desc("好好学习,天天向上").build();
System.out.println(person.toString());
}
用构建器创建的实例易于阅读和编写,较javaBean模式又更加安全,自然,自然,每种方法都会有其优点和弊端,选择合适的使用场景,会让代码更加健壮易读。
构建器模式
- 定义:将一个复杂对象的构建和表示分离,使得同样的构建过程可以创造创建不同的表示。
- 应用场景:适用于多个构造器参数,且参数包含必选和可选参数。
- 特点:类的构造器私有化,参数是静态Builder对象,构造过程就是将Builder的属性与类的属性一一映射。
- 好处:可以灵活构造复杂对象实例,解决了使用JavaBeans模式来构造的问题。
- 坏处:构造实例成本变高了,代码也变复杂了。