在Android开发中,我们一定运用到Android的Dialog,如下:
AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("Simon")
.setIcon(android.R.drawable.dialog_alert)
.setView(R.layout.view)
.create();
dialog.show();
我们可以看到,这通过一个对象然后链式调用了他的属性,最后再显示出来。这就是Android中非常常用的一种设计模式,Builder模式。目前主流的框架也都会运用到Builder模式,如:OKhttp,EventBus等都可以看到Builder模式的身影。
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
看这个定义是不是一脸懵逼,是因为定义比较抽象。我们一步一步讲解下Builder模式是怎么引入的。
假设有一个Person类,我们通过该Person类来构建一大批人,这个Person类里有很多属性,最常见的比如name,age,sex等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下。
public class Person {
private String name;
private String age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
然后我们为了方便可能会定义一个构造方法。
public Person(String name,String age,String sex)
{
this.name=name;
this.age=age;
this.sex=sex;
}
有时我们为了创建对象会定义一个空的构造方法
public Person()
{
}
甚至有时候你很懒,只想传部分参数,你还会定义如下类似的构造方法。
public Person(String name) {
this.name = name;
}
public Person(String name, String age) {
this.name = name;
this.age = age;
}
然后我们就可以创建对象了
Person p1=new Person();
Person p2=new Person("张三");
Person p3=new Person("李四","20");
Person p4=new Person("王五","21","men");
可以想象一下这样创建的坏处,我们并不能知道所传的对象的所包含的意义,不能直观的看出来。还有一个问题就是当有很多参数时,编写这个构造函数就会显得异常麻烦。或许我们会提出来用JavaBean来解决这个问题,通过setter和getter方法来设置和获取属性。代码如下:
public class Person {
private final String name;
private String age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
优点:代码可读性很好,而且创建对象清晰明了。
缺点: 构造的过程可能分到几个调用中,可能设置的属性都不是同一个对象,无法保证一致性。不能设置为final属性。
有什么方法可以解决这些问题呢?
当然是我们今天的主角。—–Builder模式。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Director:Builder接口的构造者和使用者。
适用性:
当同时满足以下情况的时候可以使用Builder模式
a. 当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式;
b. 当构造过程必须允许构造的对象有不同的表示;
1) 变种的Builder模式的目的在于减少对象创建过程中引用的多 个重载构造方法、可选参数和setters过度使用导致的不必要的复 杂性。下面以一个简单对象Person对象创建过程为例子说明,它 具有如下所示的属性,且都是不可变的final的。
public class Person {
private final String name;
private final int age;
private final double height;
private final double weight;
我们给Person增加一个静态内部类Builder类,并修改Person类的构造函数
public class Person {
private final String name;
private final int age;
private final double height;
private final double weight;
private Person(Builder builder){
this.name=builder.name;
this.age=builder.age;
this.height=builder.height;
this.weight=builder.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对象自身的另一个作用就是让它支持链式调用,使代码可读性大大增强。
于是我们就可以这样创建Person类。
Person.Builder builder=new Person.Builder();
Person person=builder
.name("Simon")
.age(20)
.height(178.5)
.weight(67.4)
.build();
最后总结一下Android Builder模式的用法:
定义一个静态内部类Builder,内部的成员变量和外部类一样
Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
Builder类提供一个build方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有构造函数,该构造函数的参数就是内部类Builder
外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的值
Builder模式的核心思想:
将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。
最后推荐大家想深入了解Builder模式的可以看看这篇博文:
[http://www.cnblogs.com/happyhippy/archive/2010/09/01/1814287.html]