前言
在开发中,经常用到builder设计模式,但感觉最常见的应用场景就是构造对象参数较多的时候,最近又用到了建造者模式,故在此梳理总结一下。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。首先这是一个复杂的对象,也就是说对象的创建过程比较复杂,可能需要N多个组件来完成整个对象的创建,这个时候为了符合“单一职责”,我们将对象的构建过程分离出来,通过建造者来完成对象组件的创建,再通过一个指挥者类完成组装生成一个完整的产品。
使用场景
- 如果一个对象有非常复杂的内部结构「这些产品通常有很多属性」,那么使用建造者模式
- 如果想把复杂对象的创建和使用分离开来,那么使用建造者模式使用相同的创建步骤可以创建不同的产品
UML图
说明:
- Builder: 抽象类,用于规范子类建造者的创建产品对象的各个组件
- ConcreteBuilder: 具体建造者,实现抽象类定义的所有方法。
- Product: 产品类,一般是一个比较复杂的对象
- Director: 负责安排已有模块的顺序,然后告诉Builder开始建造。
经典写法
- 产品类:房子对象
public class House {
// 打地基
private String foundation ;
// 盖框架
private String frame ;
// 浇筑
private String pouring ;
... 省略 setter 和 getter
}
- 抽象建造者「包工头」–Builder
public abstract class HouseBuilder {
private House house = new House();
// 打地基
public abstract void doFoundation();
// 盖框架
public abstract void doFrame() ;
// 浇灌
public abstract void dpPouring() ;
// 房子建成
public House createHouse() {
return house;
}
}
- 具体建造者「工人」–盖平房
public class PingFangBuilder extends HouseBuilder {
@Override
public void doFoundation() {
house.setFoundation("盖平房的地基");
}
@Override
public void doFrame() {
house.setFrame("盖平房的框架");
}
@Override
public void dpPouring() {
house.setPouring("盖平房的浇灌");
}
}
- 具体建造者「工人」–盖楼房
public class LouFangBuilder extends HouseBuilder {
@Override
public void doFoundation() {
house.setFoundation("盖楼房的地基");
}
@Override
public void doFrame() {
house.setFrame("盖楼房的框架");
}
@Override
public void dpPouring() {
house.setPouring("盖楼房的浇灌");
}
}
- 指挥者
public class HouseDirector {
// 指挥包工头
public House buildHouse(HouseBuilder houseBuilder){
houseBuilder.doFoundation();
houseBuilder.doFrame();
houseBuilder.dpPouring();
return houseBuilder.createHouse();
}
}
- 测试 – 盖楼房
public class Client {
public static void main(String[] args) {
HouseBuilder builder = new LouFangBuilder();
HouseDirector director = new HouseDirector();
House house = director.buildHouse(builder);
}
}
日常写法-内部Builder
上面为builder模式经典的写法,很少写的那么标准或者那么复杂,大多数情况下builder模式主要是为了防止在构建对象时传递太多的参数。
public class Person {
private String name;
private int age;
private String sex;
private String country;
private Person(String name, int age, String sex, String country) {
this.name = name;
this.age = age;
this.sex = sex;
this.country = country;
}
public static class Builder {
private String name;
private int age;
private String sex;
private String country;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setSex(String sex) {
this.sex = sex;
return this;
}
public Builder setCountry(String country) {
this.country = country;
return this;
}
public Person builder() {
return new Person(name, age, sex, country);
}
}
}
//使用
public class Client {
public static void main(String[] args) {
Person person = new Person.Builder()
.setAge(18)
.setCountry("中国")
.setName("张三")
.setSex("男")
.builder();
}
}
这种模式是建造者模式的简化变种,将Builder类置于Product类的内部,通过builder()方法完成产品的组装。虽然代码简化只有一个类,但依旧符合建造者模式的思想。
总结
建造者模式将一个复杂对象的构建与它的表示分离,使得客户端通过创建不同的建造者即可创建出不同的对象。且通过分离的方式,将复杂的创建过程分离出来,符合“单一职责”规范。新的不同对象可以通过新增建造者类生成,符合“开闭原则”。但建造者类的使用范围也有一定的限制,建造者模式创建的产品都有一定的相似性,如果所创建的产品差异性很大,则不适合建造者模式。