前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >编写高质量的代码——详解Builder模式

编写高质量的代码——详解Builder模式

作者头像
大神带我来搬砖
发布2018-05-02 14:20:39
4720
发布2018-05-02 14:20:39
举报
文章被收录于专栏:大神带我来搬砖

假设有一个用有多个属性的java bean,想在得到这个bean的时候,就已经将其属性初始化好

代码语言:javascript
复制
public class Persion {

    private int age;
    private String name;
    private String email;
    private String phone;

}

如果追求不可变性,实际应该让它只有getter方法,然后在构造函数里把属性初始化完成.然而下面这个构造函数有个问题,用户使用的时候,不看文档,很难知道后面3个字符串都是什么

代码语言:javascript
复制
    public Persion(int age, String name, String email, String phone) {
        this.age = age;
        this.name = name;
        this.email = email;
        this.phone = phone;
    }

构造这个java bean也可以使用常规的方法,即使用一个无参的构造函数

代码语言:javascript
复制
        Persion persion = new Persion();
        persion.setName("name");
        persion.setEmail("email");
        persion.setAge(10);
        persion.setPhone("phone");

这段代码的问题在哪里呢?在于输入太多!真正在IDE中敲一次会发现,每次都需要用键盘敲打"persion",然后才能按"."让IDE提示方法.这样会破坏编写代码的流畅性,没有连续按"."出现方法的快感.

有可能有同学提出一个解决方案,那就是让setter方法最后return this

代码语言:javascript
复制
    public Persion setAge(int age) {
        this.age = age;
        return this;
    }

在使用时

代码语言:javascript
复制
    persion.setName("name").setEmail("email"),setAge(10).setPhone("phone");

这样倒是可以链式调用,但是这个方案的问题在于破坏了单一职责原则,setAge方法既有副作用(改变了age变量,修改了对象的内部状态),又有返回值,实际上不是一个优雅的实现.

既要有流畅的编程体验,又要优美的代码,这时就需要builder模式了,典型的代码实现

代码语言:javascript
复制
public class Person {

    private int age;

    private String name;

    private String email;

    private String phone;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }

    public String getPhone() {
        return phone;
    }

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

    private Person(int age, String name, String email, String phone) {
        this.age = age;
        this.name = name;
        this.email = email;
        this.phone = phone;
    }

    public static PersonBuilder builder() {
        return new PersonBuilder();
    }

    public static class PersonBuilder {

        private int age;

        private String name;

        private String email;

        private String phone;

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

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

        public PersonBuilder email(String email) {
            this.email = email;
            return this;
        }

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

        public Person build() {
            return new Person(age, name, email, phone);
        }
    }

}

使用时代码如下

代码语言:javascript
复制
        Person persion = Person.builder()
                .age(10)
                .name("name")
                .email("email")
                .phone("phone")
                .build();

这样代码看起来漂亮很多

现在的builder是可变builder,因为每个方法都改变了自身的状态,并且return了this.我们也可以使用非可变的builder 例如

代码语言:javascript
复制
        public PersonBuilder phone(String phone) {
            return new PersonBuilder(this.age, this.name, this.email, phone);
        }

这样有什么好处呢,是可以提供一个基础的builder,让使用者按需定制而不会互相影响,例如

代码语言:javascript
复制
        PersonBuilder baseBuilder = Person.builder().age(10);
        Person bar = baseBuilder.email("bar").build();
        Person foo = baseBuilder.email("foo").build();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.04.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档