builder模式

Posted cowboys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了builder模式相关的知识,希望对你有一定的参考价值。

builder模式在Java中还是随处可见的,尤其是在阅读框架源码的过程中,为什么要采用builder模式编写代码呢?因为它有诸多好处,比如
1.可读性强
这是一段比较没有追求的开发同学经常的一种写法:

Person p = new Person();
p.setName("Zhang San");
p.setSex("male");
p.setAge(25);
p.setHeight("175");
p.setWeight("65");
p.setCountry("China");
p.setHomeTown("Guangzhou");


假如,他把这段代码换成Builder模式,那就变成了这样:

Person p = new Person.Builder()
            .name("Zhang San")
            .sex("male")
            .height(175)
            .weight(65)
            .country("China")
            .homeTown("Guangzhou")
            .build();

是不是看着非常简洁,写着也特别的享受!


2.可选择性强
可选择强是什么意思,例如类的属性(即成员变量)非常多,但是我们在实例化的时候可能根据不同场景,使用的属性数量不一样,那么假如我们使用的构造方法来实例化,那么就需要生成很多不同参数的构造方法,这不仅会为给类增加大量用处不大的代码,可读性也不强,相反,这时如果使用Builder模式,那在我们即便面对多变的需求,也不再怕了!
举个例子:
同样是Person类

public class Person {
    private String name;
    private String sex;
    private int height;
    private int weight;
    private int country;
    private int homeTown;

     public Person(String name, String sex) {
            this.name = name;
            this.sex = sex;
    }

    public Person(String name, String sex, int height, int weight) {
        this.name = name;
        this.sex = sex;
        this.height = height;
        this.weight = weight;
    }

    public Person(String name, int country) {
        this.name = name;
        this.country = country;
    }

    public Person(String name, int country, int homeTown) {
        this.name = name;
        this.country = country;
        this.homeTown = homeTown;
    }

    ...
}


假如们在四种场景中实例化Person时需要的参数都不一样,那么就需要我们生成四个不同的构造函数了,如上所示。假如有更多场景就需要更多的构造函数了,当然,你也可以说使用get/set方法就可以解决这个问题了,这就回到了我们第一个优点了。我这里的意思只是想表达Builder模式能够和get/set方法一样,增加我们实例化时的可选择性,避免构造函数的冗余。

了解了Builder模式的优点了之后,那么我们就需要着手自己来写一个Builder模式了,那么,究竟怎么写一个Builder模式才是比较正确的呢?
实现

同样,以Person类作为一个例子,来学习如何实现一个Builder模式的Person类。

public class Person {
    private String name;
    private String sex;
    private int height;
    private int weight;
    private int country;
    private int homeTown;

    private Person(String name, String sex, int height, int weight, int country, int homeTown) {
        this.name = name;
        this.sex = sex;
        this.height = height;
        this.weight = weight;
        this.country = country;
        this.homeTown = homeTown;
    }


    // 静态内部类
    static final class Builder {
        private String name;
        private String sex;
        private int height;
        private int weight;
        private int country;
        private int homeTown;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder setSex(String sex) {
            this.sex = sex;
            return this;
        }

        public Builder setHeight(int height) {
            this.height = height;
            return this;
        }


        public Builder setWeight(int weight) {
            this.weight = weight;
            return this;
        }

        public Builder setCountry(int country) {
            this.country = country;
            return this;
        }

        public Builder setHomeTown(int homeTown) {
            this.homeTown = homeTown;
            return this;
        }

        public Person build() {
            return new Person(name, sex, height, weight, country, homeTown);
        }
    }
}


由上面可见,首先Builder是一个静态内部类,之所以需要静态是因为Builder类需要和外部类Person剥离关系,否则就会耦合在一起,这里的Builder相当于一个独立文件的类一样的效果;其次Person类的构造方法最好是外部类不可调用的,私有的构造器,因为我们提供了Builder的方式让外部实现了对Person类的初始化,那么我们就没必要让外部直接通过构造方法的方式创建,所以最好设置为private;再之,Builder类中的每一个方法都需要返回该构造者,因为这样,我们才能在每一次设置时都是针对同一个Builder实例进行实例;最后,在build方法才进行对Person类进行初始化,这样做的好处就是可以避免过早地对Person类初始化,当然你也是可以在Builder的构造函数里就对Person就进行初始化,这个见仁见智。


总结
Builder模式,即构造者模式,如字面意思一样,我们可以形象地把它理解为:当我们需要构建一个类时,我们需要做一系列的准备工作,在准备好之后,通过build()方法,把具有我们需要功能的类构建出来。

















以上是关于builder模式的主要内容,如果未能解决你的问题,请参考以下文章

Builder设计模式,模板设计模式,Adapter设计模式笔记

builder模式-积木系列

变种 Builder 模式:优雅的对象构建方式

[05]Go设计模式:建造者模式(Builder Pattern)

设计模式Builder模式

23种设计模式之建造者模式代码实例