Java高效编程之Builder模式

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。Java高效编程之Builder模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

前言
在《Effective Java 第2版》中有提到,遇到多个构造器参数时要考虑使用构建器(Builder模式)。相比于重叠构造器(telescoping constructor)模式和JavaBeans模式,Builder模式实现的对象更利于使用。
下面从一个Person例子进行分析以上三种设计模式的使用,Person类有两个必要参数(id和name),有5个可选参数(age,sex,phone,address和desc)

1 重叠构造器模式
我们先来看看程序员一向习惯使用的重叠构造器模式,在这种模式下,你提供第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。下面看看其编程实现:

/**
* 使用重叠构造器模式
*/
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;

public Person(int id, String name) {
    this(id, name, 0);
}

public Person(int id, String name, int age) {
    this(id, name, age, "");
}

public Person(int id, String name, int age, String sex) {
    this(id, name, age, sex, "");
}

public Person(int id, String name, int age, String sex, String phone) {
    this(id, name, age, sex, phone, "");
}

public Person(int id, String name, int age, String sex, String phone, String address) {
    this(id, name, age, sex, phone, address, "");
}

public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.phone = phone;
    this.address = address;
    this.desc = desc;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
从上面的代码中,当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:

Person person = new Persion(1, “李四”, 20, “男”, “18800000000”, “China”, “测试使用重叠构造器模式”);
1
这个构造器调用通常需要许多你本不想设置的参数,但还是不得不为它们传递值。
一句话:重叠构造器可行,但是当有许多参数的时候,创建使用代码会很难写,并且较难以阅读。

2 JavaBeans模式
遇到许多构造器参数的时候,还有第二种代替办法,即JavaBeans模式。在这种模式下,调用一个无参构造器来创建对象,然后调用setter办法来设置每个必要的参数,以及每个相关的可选参数:

/**
* 使用JavaBeans模式
*/
public class Person {
//必要参数
private int id;
private String name;
//可选参数
private int age;
private String sex;
private String phone;
private String address;
private String desc;

public void setId(int id) {
    this.id = id;
}

public void setName(String name) {
    this.name = name;
}

public void setAge(int age) {
    this.age = age;
}

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

public void setPhone(String phone) {
    this.phone = phone;
}

public void setAddress(String address) {
    this.address = address;
}

public void setDesc(String desc) {
    this.desc = desc;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
这种模式弥补了重叠构造器模式的不足。创建实例很容易,这样产生的代码读起来也很容易:

Person person = new Person();
person.setId(1);
person.setName(“李四”);
person.setAge(20);
person.setSex(“男”);
person.setPhone(“18800000000”);
person.setAddress(“China”);
person.setDesc(“测试使用JavaBeans模式”);
1
2
3
4
5
6
7
8
遗憾的是,JavaBeans模式自身有着很重要的缺点。因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。

3 Builder模式(推荐)
幸运的是,还有第三种替代方法,既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。这就是Builder模式的一种形式,不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的builder方法来生成不可变的对象。这个builder是它构建类的静态成员类。下面就是它的示例:
/**
* 使用Builder模式
*/
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;

private Person(Builder builder) {
    this.id = builder.id;
    this.name = builder.name;
    this.age = builder.age;
    this.sex = builder.sex;
    this.phone = builder.phone;
    this.address = builder.address;
    this.desc = builder.desc;
}

public static class Builder {
    //必要参数
    private final int id;
    private final String name;
    //可选参数
    private int age;
    private String sex;
    private String phone;
    private String address;
    private String desc;

    public Builder(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Builder age(int val) {
        this.age = val;
        return this;
    }

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

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

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

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

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

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
注意Person是不可变得,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身。以便可以把连接起来。下面是客户端使用代码:

/**
* 测试使用
*/
public class Test {

public static void main(String[] args) {
    Person person = new Person.Builder(1, "张三")
            .age(18).sex("男").desc("测试使用builder模式").build();
    System.out.println(person.toString());
}

}
1
2
3
4
5
6
7
8
9
10
11

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/164113.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!