理解建造者模式从@lombok开始
建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在平时编码的时候,经常去使用lombok里面的一些注解,但是并没有去关注注解的实现
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
其实@Builder注解就是使用了建造者模式,借助lombok可以轻松去理解建造者模式,话不多,让我们一起探讨一下里面的实现
首先我们要构造一个User类
public class User {
//用户名
private String username;
// 密码
private String password;
// 邮箱
private String email;
// 手机号
private String phone;
// 性别
private String sex;
}
模拟@Builder的实现
第一步: 我们要在User用户的内部创建一个User的建造者(静态内部类)
该建造者包含用户的所有属性和build()
public static class UserBuilder {
private String username;
private String password;
private String email;
private String phone;
private String sex;
public UserBuilder() {
}
// 加入所有的getter方法
// 为每一个属性提供赋值的方法, 并返回当前的对象
public UserBuilder username(String username) {
this.username = username;
return this;
}
public UserBuilder password(String password) {
this.password = password;
return this;
}
public UserBuilder email(String email) {
this.email = email;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder sex(String sex) {
this.sex = sex;
return this;
}
// 加入build方法, 用于返回Useruser对象
public User build() {
return new User(this);
}
}
第二步:
在User类中加入构造方法和返回UserBuilder的builder()方法
public class User {
// 构造方法
public User(UserBuilder userBuilder) {
this.username = userBuilder.getUsername();
this.password = userBuilder.getPassword();
this.email = userBuilder.getEmail();
this.phone = userBuilder.getPhone();
this.sex = userBuilder.getSex();
}
// 创建空的Userbuilder对象
public static UserBuilder builder() {
return new UserBuilder();
}
}
第三步:测试, 可以看出使用链式的调用可以轻松的new出一个对象,并且代码十分的整洁
public static void main(String[] args) {
User user = User.builder()
.username("库里的球衣")
.password("123456")
.phone("12345678901")
.email("123456@qq.com")
.sex("男").build();
}
如果不理解lombok注解的原理,使用起来也是很爽的,但是知道了原理,用起来会很愉悦
传统的建造者模式
建造者模式图
其实这里的模式图还是很好理解的:
首先创建一个空的Product产品,交付给Builder进行创建,但是Builder创建的顺序是有Director来进行确认的,Director确认好顺序后,直接使用Builder获得产品
第一步: 还是上面的User类
class User {
//用户名
private String username;
// 密码
private String password;
// 邮箱
private String email;
// 手机号
private String phone;
// 性别
private String sex;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
第二步: 创建抽象的Builder类和具体的Builder类
// 抽象的User建造者
abstract class UserBuilder {
User user;
public abstract void username();
public abstract void password();
public abstract void email();
public abstract void phone();
public abstract void sex();
public UserBuilder(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
// 实现两个具体的建造者
class OneUserBuilder extends UserBuilder {
public OneUserBuilder(User user) {
super(user);
}
@Override
public void username() {
user.setUsername("库里的球衣");
}
@Override
public void password() {
user.setPassword("123456");
}
@Override
public void email() {
user.setEmail("123456@qq.com");
}
@Override
public void phone() {
user.setPhone("12345678901");
}
@Override
public void sex() {
user.setSex("男");
}
}
class OtherUserBuilder extends UserBuilder {
public OtherUserBuilder(User user) {
super(user);
}
@Override
public void username() {
user.setUsername("克莱");
}
@Override
public void password() {
user.setPassword("123456");
}
@Override
public void email() {
user.setEmail("123456@qq.com");
}
@Override
public void phone() {
user.setPhone("12345678901");
}
@Override
public void sex() {
user.setSex("男");
}
}
第三步: 编写一个指挥类, 用来控制建造者的执行顺序
class Director {
private UserBuilder userBuilder;
public Director(UserBuilder userBuilder) {
this.userBuilder = userBuilder;
}
public void makeUser() {
userBuilder.username();
userBuilder.email();
userBuilder.password();
userBuilder.sex();
userBuilder.phone();
}
}
第四步:测试
public class TraditionalBuilderTest {
public static void main(String[] args) {
// 创建一个空的用户
User user = new User();
// 使用具体的构造者
OneUserBuilder oneUserBuilder = new OneUserBuilder(user);
// 可以控制建造者建造的顺序
new Director(oneUserBuilder).makeUser();
User user1 = oneUserBuilder.getUser();
System.out.println(user1);
}
}
总结:
- 要知道一点就是不使用设计模式照样可以进行软件的开发,以上的代码完全可以不使用建造者模式,可以直接使用构造函数或者setter方法进行注入,如果有注入的多种情况需要创建很多的构造方法,在使用中你要顾忌传入参数的顺序,以及setter方法的连续性等问题。
- 文章最开始使用@lombok里使用的链式建造者模式是传统的建造者模式的改进,二者原理是相同的,只是链式建造者模式将Director直接交给了Client, 将建造者以静态内部类的形式构建在了产品里面。
设计模式值得我们去刻意的练习
创作不易,如果对你有所帮助,请点赞+关注,后续会给你带来更多的干货!!!