美文网首页技术文程序猿阵线联盟-汇总各类技术干货程序员
锱铢必较:编写高质量的代码——详解Builder模式

锱铢必较:编写高质量的代码——详解Builder模式

作者: 大神带我来搬砖 | 来源:发表于2018-04-25 20:29 被阅读497次

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

    public class Persion {
    
        private int age;
        private String name;
        private String email;
        private String phone;
    
    }
    

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

        public Persion(int age, String name, String email, String phone) {
            this.age = age;
            this.name = name;
            this.email = email;
            this.phone = phone;
        }
    

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

            Persion persion = new Persion();
            persion.setName("name");
            persion.setEmail("email");
            persion.setAge(10);
            persion.setPhone("phone");
    

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

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

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

    在使用时

        persion.setName("name").setEmail("email"),setAge(10).setPhone("phone");
    

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

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

    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);
            }
        }
    
    }
    
    

    使用时代码如下

            Person persion = Person.builder()
                    .age(10)
                    .name("name")
                    .email("email")
                    .phone("phone")
                    .build();
    

    这样代码看起来漂亮很多

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

            public PersonBuilder phone(String phone) {
                return new PersonBuilder(this.age, this.name, this.email, phone);
            }
    

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

            PersonBuilder baseBuilder = Person.builder().age(10);
            Person bar = baseBuilder.email("bar").build();
            Person foo = baseBuilder.email("foo").build();
    

    相关文章

      网友评论

      本文标题:锱铢必较:编写高质量的代码——详解Builder模式

      本文链接:https://www.haomeiwen.com/subject/cgtulftx.html