文章目录
建造者模式是什么?
建造者模式又叫做创建者模式,它将复杂的对象的创建过程与它的表示进行分离。建造者模式把复杂的创建过程进行了抽象,通过子类继承或者重载的方式,动态的创建对象,因此在使用建造者模式创建对象时,就不需要关心对象的创建过程了。
为什么要使用建造者模式?
- 建造者模式具有很好的封装性,它将构建和表示进行分离。
- 客户端不需要知道产品内部的组成细节,建造者之间相互独立,有利于系统的解耦。
什么时候使用建造者模式?
这一点非常重要,如果你学习一个知识都不了解它的应用场景,那么倒不如不学。
建造者模式一般用来创建比较复杂的对象,当对象中有较多并且复杂的属性时,就可以选择建造者模式来优化你的代码。
怎么使用建造者模式?
阅读完上面的内容,我们大概可以知道建造者模式
- 是为了创建一个对象;
- 对象一般是比较复杂的对象;
- 将创建对象的过程和对象的表示进行了分离
在不使用建造者模式之前,我们是如何创建对象的呢?没错,就是new,我们看一个例子,现在要创建一个房子对象,过程如下:
public class Main {
public static void main(String[] args) {
//直接new
House house1 = new House();
house1.setWall("白墙");
house1.setDoor("木门");
house1.setBed("木床");
house1.setTable("木桌");
}
}
class House {
private String wall; //墙
private String door; //门
private String table; //桌子
private String bed; //床
//省去setter和getter方法
}
}
这种方式创建对象无疑是最简单的,但同样也存在非常多的问题,比如我们在创建House时必须要知道House中的所有属性,然后给每个属性一一赋值。讲的形象一点,当你想盖一座房子时,需要知道盖房子的具体细节,是不是很麻烦?

其实在现实生活中,根本不需要这么麻烦,我们的目的很简单,就是想要一个房子,所以最简单的方式就是找到售楼处,把自己的喜欢的类型跟他们说一下,让售楼处给你一座合适的房子,如果房子还没有盖好,售楼处会联系开发商,让他们去盖房子,你这边不需要关心盖楼的细节,就等他们盖完交付到你手上即可。所以建造者模式也是从这个流程中抽象出来的一种设计模式。
传统的建造者模式
四个基本组成
我们看一下上面流程中必不可少的四个组成部分:
- 产品类:即我们最终要得到的对象,类比为房子。
- 建造者类:即直接参与构建产品的类,不需要跟客户端打交道,创建对象就是他们的任务,类比为开发商。
- 指挥类:直接跟客户端打交道,可以提供产品给客户端,但不参与创建对象,类比为售楼处。
- 客户端:使用设计模式前需要自己new产品,使用后直接找指挥类要产品。
产品类:房子
class House {
private String wall; //墙
private String door; //门
private String table; //桌子
private String bed; //床
//省略setter和getter方法
}
建造者类:开发商
一般业务比较复杂的情况下,建造者会有很多种,会根据不同的业务定制自己的逻辑,但最终的目的还是建造产品,因此可以将建造者的核心功能抽象出来,个性化的定制可以通过子类实现。
//建造者的抽象类
abstract class Builder {
//创建房子
protected House house = new House();
//核心功能,将创建好的房子提供给别人
public House build(){
return house;
}
//供子类实现个性化的需求,这里可以把方法名字起的通俗易懂些。
abstract void buildWall(String wall);
abstract void buildDoor(String door);
abstract void buildTable(String table);
abstract void buildBed(String bed);
}
//真正盖楼的阳光施工队
class SunBuilder extends Builder {
@Override
void buildWall(String wall) {
house.setWall(wall);
}
@Override
void buildDoor(String door) {
house.setDoor(door);
}
@Override
void buildTable(String table) {
house.setTable(table);
}
@Override
void buildBed(String bed) {
house.setBed(bed);
}
}
//还可以创建更多的施工队。。
指挥类:售楼处
连接开发商和客户的关键人物。
//售楼处
class SalesDirector {
//一个private的开发商
private Builder builder;
public SalesDirector(Builder builder) {
this.builder = builder;
}
//提供开发商盖好的房子
public House providHouse() {
return builder.build();
}
}
客户端
客户只需要收房子即可,不需要创建
public class Main {
public static void main(String[] args) {
//阳光开发商盖楼
SunBuilder sunBuilder = new SunBuilder();
sunBuilder.buildBed("木床");
sunBuilder.buildDoor("木门");
sunBuilder.buildWall("白墙");
sunBuilder.buildTable("木桌");
//客户直接而从售楼处拿房子即可
House house = new SalesDirector(sunBuilder).providHouse();
}
}
到此一个标准的建造者模式就完成了,通过Builder对House进行创建,然后在由指挥类Director返回给客户端,好处呢很明显,将House的创建过程交给了Builder,进行了解耦。坏处呢也很明显,跟之前相比麻烦了不少,客户端的代码也变多了。

其实这种方式我们并不常用,下面我们来让人神清气爽的的简化版建造者模式。
简化版的建造者模式
省去了指挥类,将建造者移动到产品类中。
- 在产品类中创建静态的建造者类,注意是静态内部类。
- 将产品类的属性复制到建造者类中。
- 在建造者类中为每一个属性创建赋值方法,并处理业务逻辑
- 在产品类中创建构造函数,参数为建造者类,并一一给属性赋值
- 在建造者类中创建产品对象的方法,一般是
build方法
我们还是边看代码边理解:
class House {
private String wall; //墙
private String door; //门
private String table; //桌子
private String bed; //床
//4.在产品类中创建构造函数,参数为建造者类,并一一给属性赋值
private House (Builder builder) {
this.wall = builder.wall;
this.door = builder.door;
this.table = builder.table;
this.bed = builder.bed;
}
public static Builder newBuilder(){
return new Builder();
}
//1.在产品类中创建静态的建造者类,注意是静态内部类。
static class Builder {
//2.将产品类的属性复制到建造者类中。
private String wall; //墙
private String door; //门
private String table; //桌子
private String bed; //床
//3.在建造者类中为每一个属性创建赋值方法,并处理业务逻辑
public Builder buildWall(String wall) {
this.wall = wall;
return this;
}
public Builder buildDoor(String door) {
this.door = door;
return this;
}
public Builder buildTable(String table) {
this.table = table;
return this;
}
public Builder buildBed(String bed){
this.bed = bed;
return this;
}
//5.在建造者类中创建产品对象的方法,一般是build方法
public House build(){
return new House(this);
}
}
}
客户端调用
public class Main {
public static void main(String[] args) {
House house = House.newBuilder()
.buildBed("木床")
.buildDoor("木门")
.buildTable("木桌")
.buildWall("白墙")
.build();
}
}
用这种方式即解决了客户端代码比较多的问题,也分离了对象的表示和创建过程。是不是感觉清爽了很多。不过你是否还有疑问,那我创建对象的时候不是依然要buildBed、buildTable、buildWall、buildDoor吗?由于这个案例只有简单的赋值业务,因此看不出特别大的明显,当House里面包含了非常多的类属性,有着很复杂的业务时,客户端这边看到的依然是这么点代码,更加复杂的创建过程可以写在buildXX中,而且这些方法的命名尽量设置为让调用方看一眼就知道什么意思,这样也会给复杂的业务降低不少的困难,代码的可读性也更加高。
最简单的建造者模式
如果感觉上面的建造者创建起来依然很麻烦,下面告诉大家一个非常简单的用法,不需要创建建造者,只需要使用一个注解即可。

如果是maven项目首先要添加上一个依赖,如下:
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
在产品类,也就是上面的House类上添加一个注解@Builder(toBuilder = true),既可实现上面的所有功能:
@Builder(toBuilder = true)
class House {
private String wall; //墙
private String door; //门
private String table; //桌子
private String bed; //床
}
客户端调用
public class Main {
public static void main(String[] args) {
House house = House.newBuilder()
.buildBed("木床")
.buildDoor("木门")
.buildTable("木桌")
.buildWall("白墙")
.build();
}
}
建造者模式是一种设计模式,用于将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。通过建造者类和指挥类,客户端可以更简洁地创建对象,而无需关注具体的构建细节。简化版建造者模式进一步减少了代码复杂性,通过静态内部类和链式调用实现。此外,Lombok库提供的@Builder注解能快速实现建造者模式,使代码更为简洁。
555

被折叠的 条评论
为什么被折叠?



