前言(一些废话,可以忽略)
- 这是最后一种创建型设计模式,见名知义,我们需要建造一些东西,这些东西的流程都是一样的,这样就可以进行抽象,依赖抽象,拥抱变化,go on
- PS.部分类实现见文末
解决建房子的问题
- 我们建房子,不管建什么类型的房子,都需要和水泥,砌砖,封顶,如果把建房子和这些必要的步骤组合在一起,直接创建出房子对象,当我们需要建不同类型的房子,或者需要增加修改不同类型的建造方式的时候,我们建房子这个操作就会显得很臃肿。
普通的建造者模式
- 建造者模式的逻辑很简单,就是抽象一个中间缓冲层,这样就方便了扩展,然后将建造某一个产品的步骤进行封装,以供统一调用,如下:
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public interface HouseBuilder {
void andCement();//和水泥
void brickLaying();//砌砖
void capping();//封顶
House getHouse();//获得房子
}
- 通过实现抽象的建造者来实现具体的某种类型房子的建造
/**
* 别墅
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public class FlatBuilder implements HouseBuilder {
//这里可以是聚合 也可以是组合,个人感觉没有关系
private Flat flat = new Flat();
@Override
public void andCement() {
System.out.println("FlatBuilder.andCement");
flat.setName("FLAT");
}
@Override
public void brickLaying() {
System.out.println("FlatBuilder.brickLaying");
}
@Override
public void capping() {
System.out.println("FlatBuilder.capping");
}
@Override
public House getHouse() {
this.andCement();
this.brickLaying();
this.capping();
//flat.setName("FLAT");
return flat;
}
}
- 我们建造的产品,即房子的一种,公寓
/**
* 公寓
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public class Flat implements House{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//也可以将房子抽象出来然后实现之,真正使用的时候看业务场景,我感觉这里的name还有点画蛇添足的意思
@Override
public String name() {
return "Flat";
}
}
- 最后,通过另外一个指挥类来统一建造我们想要的产品
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public class HouseDirector {
HouseBuilder builder;
public HouseDirector(HouseBuilder builder) {
this.builder = builder;
}
public void constract(){
builder.getHouse();
}
}
-
简单的捋一下,UML图就出来了,一个Builder接口,具体的建造者ConcreteBuilder聚合一个Product产品实体,我们在使用的时候通过Director聚合的ConcreteBuilder进行房子的建造
-
具体的使用如下
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public class BuilderMode {
public static void main(String[] args) {
HouseBuilder builder = new FlatBuilder();
HouseDirector director = new HouseDirector(builder);
House flat = director.constract();
System.out.println(flat.name());
}
}
- 这里可能会有疑问,怎么和工厂模式有点类似,他们的区别是啥子呢
- 仔细分析一下,我们发现,建造者模式关注的产品的构建过程,而工厂模式呢,是关注最终生成的产品结果
变形的建造者模式
- 个人感觉,变形的建造者模式可能大家使用得更频繁,至少遇见的次数更多
- 因为它有很强的标志性,在创建对象时,直接通过调用链的方式设置属性
- 然后最后通过builder()生成我们需要的对象,接下来我们直接看代码
/**
* 建造者模式 属性过多通过调用串的方式对需要的属性设值
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-22 22:20
**/
public class ImproveBuilderMode {
public static void main(String[] args) {
DemoBuilder builder = new DemoBuilder.MyBuilder().name("sss").builder();
System.out.println(builder);
}
}
class DemoBuilder {
private String name;
private String address;
private String hgight;
@Override
public String toString() {
return "DemoBuilder{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", hgight='" + hgight + '\'' +
'}';
}
private DemoBuilder() {
}
static class MyBuilder {
private DemoBuilder builder = new DemoBuilder();
public MyBuilder name(String name) {
builder.name = name;
return this;
}
public MyBuilder address(String address) {
builder.address = address;
return this;
}
public MyBuilder hgight(String hgight) {
builder.hgight = hgight;
return this;
}
public DemoBuilder builder() {
return builder;
}
}
}
- 在自己写的时候注意关键点,静态内部类,私有的构造者器即可
- 此种模式的核心优势就在多熟悉情况下,我们可以简洁的设置属性获取对象
- 与普通的建造者异同在哪里呢?可以注意到主要区别在于结构上,普通的建造者的结构更广,涉及不同的建造流程,而变形的建造者关注属性的注入(个人拙见)
- 如果我们将普通的建造者改为设置属性的话,可能就更容易理解了
总结
- 建造者模式就是这样的了,关注对象的建造过程,通过抽取共同特点,完成缓冲层的搭建,方便扩展。
- 如果没有建造对象时的共同特点(相同的方法),那可能就不太适合建造者模式了
- 关于普通的建造者模式和变形的建造者模式的区别,一方面是我的代码例子举得不恰当,另一方面,我得为自己辩解一句,设计模式关注的是设计思想,遵循相关原则即可,部分细节不用较真。当然如果你有任何问题,欢迎私信我,我们一起讨论,嘻嘻😳
愿你不舍爱与自由。