设计模式系列--构建者(Builder)模式

一、定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
概念给的很抽象,设计模式类的东西还是通过例子来熟悉还是最合适的。假设有一个Person类,我们通过该Person类来构建一大批人,这个Person类里有很多属性,最常见的比如name,age,weight,height等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下。

public class Person {
    private String name;
    private int age;
    private double height;
    private double weight;

    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

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

    public Person() {
    }

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

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

    public Person(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

定义了传部分参数的构造方法,创建需要的对象

Person p1=new Person();
        Person p2=new Person("张三");
        Person p3=new Person("李四",18);
        Person p4=new Person("王五",21,180);
        Person p5=new Person("赵六",17,170,65.4);

可以想象一下这样创建的坏处,最直观的就是四个参数的构造函数的最后面的两个参数到底是什么意思,可读性不怎么好,如果不点击看源码,鬼知道哪个是weight哪个是height。还有一个问题就是当有很多参数时,编写这个构造函数就会显得异常麻烦,这时候如果换一个角度,试试Builder模式,你会发现代码的可读性一下子就上去了。

给Person增加一个静态内部类Builder类,并修改Person类的构造函数,代码如下:

public class Person {
    private String name;
    private int age;
    private double height;
    private double weight;
//Person类的构造方法是私有的,调用者不能直接创建Person对象
    private Person(Builder builder) {
        this.name=builder.name;
        this.age=builder.age;
        this.height=builder.height;
        this.weight=builder.weight;
    }
    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 double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    static class Builder{
        private String name;
        private int age;
        private double height;
        private double weight;
        public Builder name(String name){
            this.name=name;
            return this;
        }
        public Builder age(int age){
            this.age=age;
            return this;
        }
        public Builder height(double height){
            this.height=height;
            return this;
        }

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

        public Person build(){
            return new Person(this);
        }
    }
}

从上面的代码中我们可以看到,我们在Builder类里定义了一份与Person类一模一样的变量,通过一系列的成员函数进行设置属性值,但是返回值都是this,也就是都是Builder对象,最后提供了一个build函数用于创建Person对象,返回的是Person对象,对应的构造函数在Person类中进行定义,也就是构造函数的入参是Builder对象,然后依次对自己的成员变量进行赋值,对应的值都是Builder对象中的值。此外Builder类中的成员函数返回Builder对象自身的另一个作用就是让它支持链式调用,使代码可读性大大增强。唯一可能存在的问题就是会产生多余的Builder对象,消耗内存。

Person.Builder builder=new Person.Builder();
Person person=builder
        .name("cruin")
        .age(28)
        .height(172)
        .weight(62)
        .build();

其实在Android中, Builder模式也是被大量的运用。比如常见的对话框的创建

AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("标题")
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setView(R.layout.myview)
        .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        })
        .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        })
        .create();
dialog.show();

优缺点

优点:
良好的封装性,使得客户端不需要知道产品内部实现的细节建造者独立,扩展性强

缺点:
产生多余的Builder对象、Director对象(不一定存在,取决于使用的哪种Builder模式),消耗内存

你可能感兴趣的:(设计模式系列--构建者(Builder)模式)