一、概述
建造者模式也叫生成器模式,23种设计模式之一,属于创建类模式。
在描述建造者模式之前,大家首先要明白一个道理就是任何设计模式的产生都是为了解决某一类问题,更准确的说是为了应对某一种变化,设计模式就是封装变化,把变化的部分和不变的部分隔离开。设计模式的好处就是运用面向对象的思想让我们能够更简单方便的应对外界需求的变化。比如工厂模式的产生是由于我们要根据外界的需求生产出不同类型的产品,这一变化就是外界的需求是不确定的,工厂模式就是为了应对这种变化而产生。那建造者模式是为了应对哪一种变化呢?
首先还是看下GOF对建造者模式的定义:将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建出不同的表示。
看到有网友用KFC的例子来描述建造者模式,我觉得还是比较贴近的,我们也借用这个例子描述一下:
假设KFC推出两种套餐:奥尔良鸡腿堡套餐和香辣鸡腿堡套餐,奥尔良套餐包括:一个奥尔良鸡腿堡、一个炸鸡翅、一杯雪碧。鸡腿堡套餐包括:一个香辣鸡腿堡、一份薯条、一杯可乐。每份套餐都是:主食、副食、饮料。
KFC服务员要根据顾客的要求来提供套餐,那这个需求里面什么是固定的,什么是变化的呢?很明显顾客都是要的套餐,顾客的目的是一样的。 套餐里面都是主食、副食、饮料,这也是固定的。至于主食是什么、副食是什么、饮料是什么这个是变化的。
二、使用场景
当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config、VO、PO、Entity...),要创建的话可能就需要了解这个类的内部结构。并且为了适应构建多个不同对象,可能要生成多个不同的类构造器。此时缺点就出来了,一个是需要构建多个构造器,如果参数类型和参数个数相同还不能方法重载,一个是在调用时传入多个参数时可读性差,如果粗心顺序搞错了会造成参数误传。此时 Builder模式的使用就很好的解决了上面的问题。
三、Builder模式的实现
@TableName("user") @Data public class User { private Long id; private String userName; private Integer age; private String email; private Date birth; private User(Builder builder) { setId(builder.id); setUserName(builder.userName); setAge(builder.age); setEmail(builder.email); setBirth(builder.birth); } public static final class Builder { private Long id; private String userName; private Integer age; private String email; private Date birth; public Builder() { } public Builder id(Long val) { id = val; return this; } public Builder userName(String val) { userName = val; return this; } public Builder age(Integer val) { age = val; return this; } public Builder email(String val) { email = val; return this; } public Builder birth(Date val) { birth = val; return this; } public User build() { return new User(this); } } }
public static void main(String[] args) { User user = new User.Builder().userName("张三").age(10).email("123@qq.com").build(); System.out.println(user); }
四、Builder模式自动化生成Plugin