java构造者模式_折腾Java设计模式之建造者模式

建造者模式

Separate the construction of a complex object from its representation, allowing the same construction process to create various representations.

将复杂对象的构造与其表现分离,允许相同的构造过程用来创建不同的表现。通俗点就是,一个对象创建过程很复杂,我们将其每项元素创建过程抽离出来,通过相同的构造过程可以构造出不用的对象。还不懂可以看到如下的UML图。

建造者模式UML图

2f636f8561094d155b2a6d7798741405.png

此AbstractPersonBuilder就是如上的相同的构造,而不同的表现就是此处的PersonOneBuilder和PersonTwoBuilder两个相同方式的构造器,但是具体的实现是不一样而构造出不同的表现。所以就是相同的构造过程而构造出不同的对象。

建造者模式角色

抽象建造者(AbstractPersonBuilder或者Builder):抽象类或者接口,复杂对象的属性的抽象方法,并不涉及具体的对象部件的创建;

具体建造者(PersonOneBuilder和PersonTwoBuilder):实现抽象建造者,针对不同的业务,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例;

指挥者(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建;

具体的产品(Person):需创建的复杂对象;

建造者模式源码干货

源码地址:请点击我

在这里我分为三种情况讲讲建造者模式,第一种是我们最原始的建造者模式来构建,第二种是我们在实体对象时会使用的,第三种是我们平常对实体对象最常规使用方法借助lombok。

第一种建造者模式

使用的真是上面按照角色来建造的方式,稍微比如下的两种方法负责点。

抽象建造者

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 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 getChildren() {

return children;

}

public void setChildren(List 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);

}

}

结果:

5b82ed3440f789142c88aecf297f5855.png

第二种建造者模式

第二种方式比上面那种简单些,因为我们只指定了一种构造方式,并且还可以借用第三方工具IDEA+Plugins。

在IDEA中可以搜索

c794480bb01ec77b0d2c1820b5c16616.png

使用方法:

1.找到对应需要添加bulid的类通过自动生成快捷键可以查看到build

142be733d902ec448cdfef5036fcbdb8.png

2.根据自己的风格可以定义bulid的名字,各个bulid方法的前缀以及包名,具体bulider如下代码中。

56b07617f273bf98c6340eaaea653c14.png

PersonBuilder用来Person的构建者

public final class PersonBuilder {

private String name;

private int age;

private List 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 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 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 getChildren() {

return children;

}

public void setChildren(List 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);

}

}

结果如下:

8c6dc6f9bab1d3b20afa769c8924ea50.png

第三种建造者模式

第三种模式相对来说就简单非常多,因为我们借用的是lombok的@Builder注解。lombok在18.2版本中引入了@SuperBulider注解用来解决@Builder类的继承不生效的问题。详细的使用阔以看我上篇文章 折腾Java设计模式之模板方法模式

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class Person {

private String name;

private int age;

private List 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);

}

}

结果:

ca9b713e421642155987098ceaa32d8e.png

总结

第二、三种模式在我们经常操作像对VO、DO、DTO对象时,常用如此定义。第一种标准的建造者模式,其实本身指挥者这个角色是不关心具体的产品实现的,相对于是一种解耦,对于如果新增一种建造者实现,可以方便扩展,符合开闭原则,但是无独有偶,实现了上述优点后,但是缺点也跟着来,新增了很多类,维护成本高,如果建造者内部发生变更,就不太适合建造者这种模式了。总体而言还是有很多使用场景的。像StringBulider其实也是一种。像之前在spring-boot的spring-cache中的扩展redis缓存的ttl和key名这篇文章中定义的RedisCacheManagerBuilder,以及我们常用的以后要讲的Feign的Builder等等。

欢迎关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值