说明
将 一个 复杂对象 的 构建过程 与 使用 分离 , 使得 同样的构建过程 , 可以 创建不同的表示 ;
用户只需要 指定 需要建造的类型 就可以 得到该类型对应的产品实例 , 不关心建造过程细节 ;
建造者模式类型 : 创建型 ;
应用场景
- 对象有 非常复杂的内部结构,有很多属性 ;
- 把 复杂对象 的 创建 和 使用 分离 ;
- 当创造一个对象 需要 很多步骤时 , 适合使用建造者模式 ;
真实案例
- flink的
JdbcConnectionOptions类构建过程
优点
封装性好 : 创建 和 使用 分离 ;
扩展性好 : 建造类之间 相互独立 , 在 一定程度上解耦 ;
缺点
增加类数量 : 产生多余的 Builder 对象 ;
内部修改困难 : 如果 产品内部发生变化 , 建造者也要相应修改 ;
角色
所谓角色,表示分哪几种类
产品(Product):也就是要建造的对象,一般是较为复杂的对象,由一系列部件组成
抽象建造者(builder):其实就是接口或抽象类,表示建造者必须实现的方法。定义具体建造者的公开方法
具体建造者(ConcreteBuilder):抽象建造者的实现类,产品对象是 复杂对象,构建过程可能涉及 多个步骤 和 配置选项,所以作用:
创建产品对象
调用产品对象的
setXXX()方法,给产品成员变量赋值按照顺序调用产品对象的方法,以完成构建
指挥者(Director):调用具体建造者来创建复杂对象(产品),并且是按照一定顺序(流程)。(普通程序员就是调用该类来完成创建对象的)
案例
盖楼,需要设置 名称、层数、面积
调用 修建地基、盖楼、封顶 方法
注意:
- 创建对象时,必须调用
修建地基、盖楼、封顶方法 - 方法有调用顺序
产品类
这是的 House 类,就是产品类
package day3;
public class House {
/**
* 楼的名字
*/
private String name;
/**
* 房子的层数
*/
private int floor;
/**
* 面积
*/
private double area;
public void diji(){
System.out.println("修建地基");
}
public void gailou(){
System.out.println("盖楼");
}
public void fengding(){
System.out.println("封顶");
}
public String getName() {
return name;
}
public int getFloor() {
return floor;
}
public double getArea() {
return area;
}
public void setName(String name) {
this.name = name;
}
public void setFloor(int floor) {
this.floor = floor;
}
public void setArea(double area) {
this.area = area;
}
}
抽象建造者
其实就是接口
// 抽象建造者
interface HouseBuilder {
void setName(String name);
void setFloor(int floor);
void setArea(double area);
// 修筑地基,方法是动词所以加build
void buildDiji();
void gailou(); // 盖楼
void fengding(); // 封顶
House getProduct();
}
具体建造者
抽象建造者的实现类
class HouseBuilderImpl implements HouseBuilder{
// 产品类对象
private House house = new House();
public void setName(String name) {
house.name = name;
}
public void setFloor(int floor) {
house.floor = floor;
}
public void setArea(double area) {
house.area = area;
}
// 修筑地基,方法是动词所以加build
public void buildDiji(){
house.diji();
}
void gailou(){ // 盖楼
house.gailou();
}
void fengding(){ // 封顶
house.fengding();
}
public House getProduct(){
return house;
}
}
指挥官
// 指挥者
class Director {
private HouseBuilder builder;//接口类型
public Director(HouseBuilder builder) {
this.builder = builder;
}
public House build(String name,int floor,double area) {
// 设置产品的成员变量
builder.setName(name);
builder.setFloor(floor);
builder.setArea(area);
//指挥建造者来一步步创建,注意:这些方法有调用顺序,先地基,然后盖楼,最后封顶
// 先建地基
builder.diji();
// 然后盖楼
builder.gailou();
// 最后封顶
builder.fengding();
return house.getProduct();
}
}
客户端使用
// 客户端代码,普通程序员编写的代码
public class BuilderExample {
public static void main(String[] args) {
// 创建建造者对象
HouseBuilder builder = new HouseBuilderImpl();
//创建指挥官对象,builder建造者对象传入指挥者对象
Director director = new Director(builder);
// 创建对象
House house = director.build();
System.out.println(house);
}
}
简化建造者
package day3;
public class House {
/**
* 楼的名字
*/
private String name;
/**
* 房子的层数
*/
private int floor;
/**
* 面积
*/
private double area;
protected House(String name, int floor, double area) {
this.name = name;
this.floor = floor;
this.area = area;
}
public void diji(){
System.out.println("修建地基");
}
public void gailou(){
System.out.println("盖楼");
}
public void fengding(){
System.out.println("封顶");
}
public String getName() {
return name;
}
public int getFloor() {
return floor;
}
public double getArea() {
return area;
}
// 定义内部建造者类,通过该类创建产品对象
static class Builder{
/**
* 楼的名字
*/
private String name;
/**
* 房子的层数
*/
private int floor;
/**
* 面积
*/
private double area;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setFloor(int floor) {
this.floor = floor;
return this;
}
public Builder setArea(double area) {
this.area = area;
return this;
}
/**
* 在该方法中构建对象
* @return
*/
public House build(){
House house = new House(name, floor, area);
// 先建地基
house.diji();
// 然后盖楼
house.gailou();
// 最后封顶
house.fengding();
return house;
}
}
}
参考:
https://developer.aliyun.com/article/864600
https://www.jianshu.com/p/47329a94f5dc