美文网首页
设计模式分享之Builder Pattern

设计模式分享之Builder Pattern

作者: 不可诗意之刀老大 | 来源:发表于2018-09-17 09:08 被阅读0次

    场景问题

    考虑以下场景,有一个 User 用户类,该类有很多属性。

    public class User {
        
        private String userName;     // 必传参数:用户名
        private String password;      // 必传参数:密码
        private int age;              // 可选参数:年龄
        private String phone;         // 可选参数:手机号
        private String address;       // 可选参数:地址
    
    }
    

    上面有些字段是必要的,有些是非必须的,那么问题来了,如何创建这个类的对象呢?

    方法一:构造方法重载

    public User(String userName, String password) {
            this(userName, password, 0);
        }
    
        public User(String userName, String password, int age) {
            this(userName, password, age, "");
        }
    
        public User(String userName, String password, int age, String phone) {
            this(userName, password, age, phone, "");
        }
    
        public User(String userName, String password, int age, String phone, String address) {
            this.userName = userName;
            this.password = password;
            this.age = age;
            this.phone = phone;
            this.address = address;
     }
    

    可以正常运行,但有以下几个问题:

    • 后续参数增加改动量大;
    • 调用者麻烦,只想多传一个参数address时,还必需给 age,phone 设置默认值。此外,参数顺序不易对应。

    方法二:Setter和 Getter

        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    

    可读性不错,易于维护。作为调用者来说,创建一个空对象,然后只传入感兴趣的参数即可,但也有缺点:

    • 对象产生不一致的状态,如果要传入5个参数,必需将所有的 setXX方法调用完成之后才行。
    • User 是可变的,在某些场合需要创建之后不可变。

    重点:对象创建之后不可变,不可变对象天生就是线程安全的。

    方法三:Builder Pattern

    public class User {
    
        private final String userName;     // 必传参数
        private final String password;      // 必传参数
        private final int age;              // 可选参数
        private final String phone;         // 可选参数
        private final String address;       // 可选参数
    
        private User(UserBuilder builder) {
            this.userName = builder.userName;
            this.password = builder.password;
            this.age = builder.age;
            this.phone = builder.phone;
            this.address = builder.address;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public String getPassword() {
            return password;
        }
    
        public int getAge() {
            return age;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public String getAddress() {
            return address;
        }
    
        public static class UserBuilder {
            private final String userName;
            private final String password;
            private int age;
            private String phone;
            private String address;
    
            public UserBuilder(String userName, String password) {
                this.userName = userName;
                this.password = password;
            }
    
            public UserBuilder age(int age) {
                this.age = age;
                return this;
            }
    
            public UserBuilder phone(String phone) {
                this.phone = phone;
                return this;
            }
    
            public UserBuilder address(String address) {
                this.address = address;
                return this;
            }
    
            public User build() {
                return new User(this);
            }
        }
    
    }
    

    注意事项:

    • User类构造方法是私有的,调用者不能直接创建User 对象;
    • User类对象属性不可变,final 修饰,对外只提供 Getter 方法;
    • Builder链式调用,可读性更加;
    • Builder的内部类构造方法中只接收必传的参数,并且该必传的参数适用了final修饰符

    现在,如何创建一个 User对象呢?

    new User.UserBuilder("yintangwen952", "******")
                    .age(20)
                    .phone("12345678901")
                    .address("平安金融中心")
                    .build();
    

    一行代码解决问题!

    经典示例

    1.Android(AlertDialog)

    AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("提示")
                    .setMessage("确定退出?").create();
            dialog.show();
    

    2.开源库(Picasso,Glide [ɡlaɪd])

    Picasso.with(context)
    .load("https://square.github.io/picasso/static/sample.png")
    .into(imageView);
    
    Glide.with(context)
     .load(url)
     .centerCrop()
     .placeholder(R.drawable.default_img)
     .crossFade()
     .into(imageView);
    

    相关文章

      网友评论

          本文标题:设计模式分享之Builder Pattern

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