第2条:遇到多个构造器参数时要考虑用构建器

来源:互联网 发布:linux 禁用ping 编辑:程序博客网 时间:2024/05/16 19:26

无论是静态工厂还是构造器都有共同的局限性:它们都不能很好地扩展到大量可选参数。

然后重叠构造器模式可以实现这一需求,但是又许多参数的时候,客户端代码会变得很难编写,并且可读性很差

于是我们想到JavaBean模式,在这种模式下,调用一个无参构造器来创建对象,然后使用setter来对每个参数进行设置,例:

        Book book = new Book();        book.setName("xx");        book.setPrice(123);

这样就出现了一个问题,由于对Book类的参数设置是多个setter方法,这个类可能会处于不一致状态,会导致难以调试的错误。

因此我们说JavaBeans模式阻止了把类做成不可变的可能(即不能做到线程安全)

那么我们会想,有没有一种模式既能保证像JavaBeans模式那样的可读性,又能保证像重叠构造器模式那样的安全性?

有,那就是Builder模式

Builder模式的做法:
1.这个模式不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。
2.然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用build()方法来生产不可变对象。

下面是Book的Builder模式的代码

public class Book{    private String name;    private float price;    private String authorName;    //这里有很多参数没写出来    //这是Builder,Book类的内部类    public static class Builder{        private String name;        private float price;        private String authorName;        //这是Builder的狗构造器        public Builder(){        }        //Builder的setter方法,注意这里返回值是自身,链式编程        public Builder name(String val){            name = val;            return this;        }        //这里有很多参数的setter没写出来        //还有一个重要方法,builder方法,用于生成真正的对象,这里是Book的实例        public Book builder(){            return new Book(this);        }    }    //这是Book的构造器,只接受一个参数,那就是已经构建好的builder    private Book(Builder builder){        name = builder.name;        price = builder.price;        //这里有很多赋值没写出来    }}

以下是客户端代码:

Book book = new Book.Builder().name("书名").price(12).省略.builder();

注意:Builder模式的参数校验应该放在setter方法中,而不是在builder()方法中。

当然,Builder模式也有自身的不足,因为每次为了创建对象,都要先创建Builder的狗构造器。
在某些十分注重性能的情况下,可能会发生问题。

并且,最好在类设计时一开始就是用Builder,而不是构造器和Builder共存

简而言之,如果类的构造器或静态工厂中具有多个参数,设计这种类时,Builder模式是不错的选择,特别是当大多数参数是可选的时候。

0 0
原创粉丝点击