博文原址:折腾Java设计模式之建造者模式java
Separate the construction of a complex object from its representation, allowing the same construction process to create various representations.git
将复杂对象的构造与其表现分离,容许相同的构造过程用来建立不一样的表现。通俗点就是,一个对象建立过程很复杂,咱们将其每项元素建立过程抽离出来,经过相同的构造过程能够构造出不用的对象。还不懂能够看到以下的UML图。github
此AbstractPersonBuilder
就是如上的相同的构造,而不一样的表现就是此处的PersonOneBuilder
和PersonTwoBuilder
两个相同方式的构造器,可是具体的实现是不同而构造出不一样的表现。因此就是相同的构造过程而构造出不一样的对象。redis
抽象建造者(AbstractPersonBuilder
或者Builder
):抽象类或者接口,复杂对象的属性的抽象方法,并不涉及具体的对象部件的建立;spring
具体建造者(PersonOneBuilder
和PersonTwoBuilder
):实现抽象建造者,针对不一样的业务,具体化复杂对象的各部分的建立。 在建造过程完成后,提供产品的实例;设计模式
指挥者(Director
):调用具体建造者来建立复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整建立或按某种顺序建立;缓存
具体的产品(Person
):需建立的复杂对象;微信
源码地址:请点击我ide
在这里我分为三种状况讲讲建造者模式,第一种是咱们最原始的建造者模式来构建,第二种是咱们在实体对象时会使用的,第三种是咱们日常对实体对象最常规使用方法借助lombok。spring-boot
使用的真是上面按照角色来建造的方式,稍微好比下的两种方法负责点。
抽象建造者
public abstract class AbstractPersonBuilder {
protected Person product = new Person();
public abstract void buildName();
public abstract void buildAge();
public abstract void buildChildren();
public Person build() {
return product;
}
}
复制代码
第一个具体建造者
public class PersonOneBuilder extends AbstractPersonBuilder {
public void buildName() {
product.setName("老one");
}
public void buildAge() {
product.setAge(44);
}
public void buildChildren() {
product.setChildren(Lists.newArrayList("小one"));
}
}
复制代码
第二个具体建造者
public class PersonTwoBuilder extends AbstractPersonBuilder {
public void buildName() {
product.setName("老two");
}
public void buildAge() {
product.setAge(55);
}
public void buildChildren() {
product.setChildren(Lists.newArrayList("小two"));
}
}
复制代码
Person类充当产品数据
public class Person {
private String name;
private int age;
private List<String> children;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", children=" + children +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getChildren() {
return children;
}
public void setChildren(List<String> children) {
this.children = children;
}
}
复制代码
指挥者,指定具体的建造者用来建造对象
public class Director {
private AbstractPersonBuilder builder;
public Director(AbstractPersonBuilder builder) {
this.builder = builder;
}
public void setBuilder(AbstractPersonBuilder builder) {
this.builder = builder;
}
public Person construct() {
builder.buildName();
builder.buildAge();
builder.buildChildren();
return builder.build();
}
}
复制代码
示例
@Slf4j
public class Application {
public static void main(String[] args) {
Director director = new Director(new PersonOneBuilder());
Person person = director.construct();
log.info("person的信息:{}", person);
director.setBuilder(new PersonTwoBuilder());
person = director.construct();
log.info("person的信息:{}", person);
}
}
复制代码
结果:
第二种方式比上面那种简单些,由于咱们只指定了一种构造方式,而且还能够借用第三方工具IDEA+Plugins。
在IDEA中能够搜索
使用方法:
1.找到对应须要添加bulid的类经过自动生成快捷键能够查看到build
2.根据本身的风格能够定义bulid的名字,各个bulid方法的前缀以及包名,具体bulider以下代码中。
PersonBuilder用来Person的构建者
public final class PersonBuilder {
private String name;
private int age;
private List<String> children;
private PersonBuilder() {
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public PersonBuilder withName(String name) {
this.name = name;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public PersonBuilder withChildren(List<String> children) {
this.children = children;
return this;
}
public Person build() {
Person person = new Person();
person.setName(name);
person.setAge(age);
person.setChildren(children);
return person;
}
}
复制代码
Person类充当产品数据
public class Person {
private String name;
private int age;
private List<String> children;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", children=" + children +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getChildren() {
return children;
}
public void setChildren(List<String> children) {
this.children = children;
}
}
复制代码
示例
@Slf4j
public class Application {
public static void main(String[] args) {
Person wang = PersonBuilder.builder()
.withAge(40)
.withName("老王")
.withChildren(Lists.newArrayList("李一一", "吴老三"))
.build();
log.info("老王的信息:{}", wang);
}
}
复制代码
结果以下:
第三种模式相对来讲就简单很是多,由于咱们借用的是lombok的@Builder注解。lombok在18.2版本中引入了@SuperBulider注解用来解决@Builder类的继承不生效的问题。详细的使用阔以看我上篇文章 折腾Java设计模式之模板方法模式
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private int age;
private List<String> children;
}
复制代码
@Slf4j
public class Application {
public static void main(String[] args) {
Person wang = Person.builder()
.age(40)
.name("老王")
.children(Lists.newArrayList("李一一", "吴老三"))
.build();
log.info("老王的信息:{}", wang);
}
}
复制代码
结果:
第2、三种模式在咱们常常操做像对VO、DO、DTO对象时,经常使用如此定义。第一种标准的建造者模式,其实自己指挥者这个角色是不关心具体的产品实现的,相对因而一种解耦,对于若是新增一种建造者实现,能够方便扩展,符合开闭原则,可是无独有偶,实现了上述优势后,可是缺点也跟着来,新增了不少类,维护成本高,若是建造者内部发生变动,就不太适合建造者这种模式了。整体而言仍是有不少使用场景的。像StringBulider其实也是一种。像以前在spring-boot的spring-cache中的扩展redis缓存的ttl和key名这篇文章中定义的RedisCacheManagerBuilder,以及咱们经常使用的之后要讲的Feign的Builder等等。
欢迎关注