Effective Java---------遇到多个构造器参数时考虑使用构建器

静态工厂方法和构造器有个共同的局限性,他们不能很好地扩展到大量的可选参数。对于有多种可选参数的类而言,可以使用以下几种方式:

1、重叠构造器

重叠构造器,提供的第一个构造器只有必要的参数,第二个构造器有一个可选参数,第三个构造器有两个可选参数,以此类推,如下代码所示。

public class Person {
    private String name ;
    private int age;
    private String gender;

    private String education;
    private String people;
    private String nationality;

    public Person(String name, int age, String gender) {
        this(name, age, gender, null);
    }

    public Person(String name, int age, String gender, String education) {
        this(name, age, gender, education, null, null);
    }

    public Person(String name, int age, String gender, String education, String people, String nationality) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.education = education;
        this.people = people;
        this.nationality = nationality;
    }
}

重叠构造器模式是可行的,但是当有许多参数的时候,客户端代码会很难编写,并且较难以阅读。并且如果不小心颠倒了其中的参数,编译器也不会报错,但是程序在运行中会出现错误。

2、JavaBean模式

最常见的一种形式,先调用无参构造器创建出对象,再用setter方法进行赋值。这种模式弥补了重叠构造器模式的不足,即创建实例很容易,且代码阅读方便。但是JavaBean模式也存在着缺陷,因为构造过程被分割到了几个调用中,在构建过程中JavaBean可能处于不一致状态。并且JavaBean模式使得将类做成不可变类的可能性不复存在。(在多线程环境中,可能刚创建好实例,但还没有进行赋值,就被其他线程使用,出现不一致情况。使用JavaBena模式且使用无参构造器时,参数无法使用final修饰,因此类可变。)

3、构建器(Builder)模式

它既能保证像重叠构造器模式那样的安全性,也能保证像JavaBean模式那么好的可读性,这就是建造者模式的一种形式。它不直接生成对象,而是利用所有必要的参数调用构造器(或静态工厂),得到一个builder对象。让然后在builder对象上调用类似于setter的方法,来设置每个相关的参数。最后在调用builder的无参的build方法来生成通常是不可变的对象。

也就是,先进行赋值(间接),再创建对象。

public class Person {
    private final String name ;
    private final int age;
    private final String gender;

    private final String education;
    private final String people;
    private final String nationality;

    private Person(Builder builder){
        this.name = builder.name;
        this.age = builder.age;
        this.gender = builder.gender;
        this.education = builder.gender;
        this.people = builder.people;
        this.nationality = builder.nationality;
    }

    public static class Builder{
        private String name;
        private int age;
        private String gender;
        private String education;
        private String people;
        private String nationality;

        public Builder(String name, int age, String gender){
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        public Builder education(String education){
            this.education = education;
            return this;
        }
        public Builder people(String people){
            this.people = people;
            return this;
        }
        public Builder nationality(String nationality){
            this.nationality = nationality;
            return this;
        }
        public Person build(){
            return new Person(this);
        }
    }
}


Person person = new Person.Builder("A", 16, "male").education("bachelor").people("han").nationality("China").build();

与构造器相比,builder的微略优势在于,它可以有多个可变参数。因为builder是利用单独的方法来设置每一个参数。此外,构造器还可以将多次调用某一个方法而传入的参数集中到一个域中。Builder模式十分灵活,可以利用单个builder创建多个对象。builder的参数可以在调用build方法来创建对象期间进行调整,也可以随着不同的对象而改变。builder可以自动填充某些域,例如增加序列号。

Builder模式的确有它自身的不足,为了创建对象,必须先创建它的构建器。在某些十分注重性能的情况下创建构造器的开销可能是个问题。Builder模式还比重叠构造器模式还要冗长,因此它旨在有很多参数的时候才使用。

简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是一种不错的选择,特别是当大多数参数都是可选或者类型相同的时候。与使用重叠构造器相比,使用Builder模式的代码将更易于阅读与编写,构建器也比JavaBean更加安全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值