持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
简述
属于创建型模式 ,将一个复杂的构建与其表示相分离,可以自行选择不同组合构建出想要的对象。
优点
- 建造者独立,易扩展。
- 便于控制细节风险。
- 可以基于不同组合建造出各种各种各样的对象。
缺点
- 产品需要有共同点,范围边界有限制。
- 如果内部变化复杂会有很多的建造类。
实现
简单的Builder
需求:构建一个复杂地图,地图中包含堡垒、墙、矿等等,构建地图的使用者,需要构建各种各样的地图,且并不一定全都需要构建。
Terrain对象,Fort、Mine、Wall以内部类的形式呈现
// 地图
public class Terrain {
Wall w;
Fort f;
Mine m;
}
// 墙
class Wall {
int x, y, w, h;
public Wall(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
// 堡垒
class Fort {
int x, y, w, h;
public Fort(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
// 矿
class Mine {
int x, y, w, h;
public Mine(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
TerrainBuilder接口,定义通用方法
public interface TerrainBuilder {
TerrainBuilder buildWall();
TerrainBuilder buildWall(int x, int y, int w, int h);
TerrainBuilder buildFort();
TerrainBuilder buildMine();
Terrain build();
}
ComplexTerrainBuilder建造者实现类
public class ComplexTerrainBuilder implements TerrainBuilder {
Terrain terrain = new Terrain();
@Override
public TerrainBuilder buildWall() {
terrain.w = new Wall(10, 10, 50, 50);
return this;
}
public TerrainBuilder buildWall(int x, int y, int w, int h) {
terrain.w = new Wall(x, y, w, h);
return this;
}
@Override
public TerrainBuilder buildFort() {
terrain.f = new Fort(10, 10, 50, 50);
return this;
}
@Override
public TerrainBuilder buildMine() {
terrain.m = new Mine(10, 10, 50, 50);
return this;
}
@Override
public Terrain build() {
return terrain;
}
}
使用
使用的时候,可以根据需要构建不同的地图,比如我不需要Mine,就可以不构建Mine的build,可以自定义指定Wall的尺寸等
public class Main {
public static void main(String[] args) {
TerrainBuilder builder = new ComplexTerrainBuilder();
Terrain t = builder
.buildFort()
.buildWall(1, 2, 3, 4)
.build();
}
}
实战Factory + Builder
在真实项目中我们很多对象的构建,可能时仅仅时new出来的,可能不少信息都是需要调用接口或者查询DB才能完全构建,因此通常会有Factory的角色,在factory里构建复杂对象。 在构建复杂对象时同样会遇到和Builder的需求,能够灵活组装的构建出想要的对象。
@Component
public class DemoFactory {
DemoEntityBuilder builder(DemoListQuery demoListQuery) {
// 转化成builder
return new DemoEntityBuilder().init(demoListQuery);
}
@AllArgsConstructor
@NoArgsConstructor
public static class DemoEntityBuilder {
DemoListQuery demoListQuery;
List<DemoEntity> resultList;
DemoEntityBuilder init(DemoListQuery demoListQuery){
this.demoListQuery = demoListQuery;
// TODO 根据条件查询DB 生成DemoEntity
resultList = new ArrayList<>();
return this;
}
public DemoEntityBuilder buildCreator(){
return this;
}
public DemoEntityBuilder buildInfo(){
return this;
}
public DemoEntityBuilder buildLocation(){
return this;
}
public List<DemoEntity> build(){
return resultList;
}
}
}
- 在这种情况下,我们可以把builder内置在Factory中
- Factory注入到Spring容器中,同时也免不了注入Repository和其他的Service来查询
- 在init中进行DB查询,构建出领域对象
- 然后通过各个build去组装领域对象中的详细信息
进阶
- buildxxx中可以是用callabe,然后再build的中用线程池批量进行查询