设计模式拙见--Builder模式

794 阅读5分钟
原文链接: blog.csdn.net

相信在面试中,面试官问到你对哪些设计模式比较熟悉了解呢?相信Builder(建造者)模式是你的其中一个答案之一,因为在实际开发中,Builder(建造者)模式是我们接触相对比较多的一种设计模式了,但是你是否真的了解它呢?首先,Builder模式如其中文译名–建造者模式的字面意思一样,就是由一系列的方法构造成,在使用起来非常的精简明了。

用法

如果你是一名Android开发者,相信你对AlertDialog的使用不陌生吧:

AlertDialog dialog = new AlertDialog.Builder(getContext())
            .setTitle("标题")
            .setMessage("内容")
            .setPositiveButton("确定", null)
            .setPositiveButton("取消", null)
            .create();
dialog.show();

AlertDialog通过内部类AlertDialog.Builder一连串的链式调用,最后通过create()方法,生成AlertDialog。这里的写法就是我们常说的Builder模式,,在使用图片加载框架Glide时也同样如此:

Glide.with(mContext)
 .load(url)
 .centerCrop()
 .placeholder(R.drawable.default_img)
 .crossFade()
 .into(mImageView);

由此可见,Builder模式在实际开发中是随处可见的,如果你作为一名有追求的开发者,开发中,在必要时也是可以使用Builder模式来进行开发。那么这时,我们就会思考,我们为什么需要使用Builder模式来coding,其实就是一个问题,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的代码量,所以还是需要根据不同的场景进行定夺,不然设计模式的滥用也是我们成为有追求的程序员的误区之一。

注:以上仅是作者的一些拙见,受限于能力,有错之处欢迎指出!