场景问题
考虑以下场景,有一个 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);
网友评论