设计模式——建造者模式

建造者模式(将产品,建造者,建造规范,指挥者分开)

场景:盖房子

直接想到的方式是将房子的属性,建造房子的步骤,以及调用这些步骤建造的过程都封装到一个类里面,具体的步骤设计为抽象方法,交给子类去实现

这样做将房子和建造房子的过程耦合在了一起,我们将建造房子的过程分离出来,就成了建造者。这样职责更加分明,耦合度更低

建造者模式的四个角色

image-20220528011810239

image-20220528012013315

  1. product就是我们需要建造的产品
  2. Builder是建造者的抽象层,用于定义有哪些建造的步骤,具体的实现由子类来完成。同时会调用Director来建造产品而不关心产品的建造过程
  3. Director负责调用Builder中的步骤完成建造过程,而不关心具体的实现
  4. 子类只需要实现建造的具体步骤,供Director来调用即可

Director只负责掌管产品制造的顺序,Builder负责实现产品每一步的生产过程

Director相当于盖房子的指挥者,AbstractBuilder相当于应聘要求,Builder则是实际干活的工人

这样如果建造流程发生了变化,只用修改Director就行了,如果有不同的解决方案,我们只需要创建不同的Director即可,建造不同的房子我们创建对应的Builder即可(如果像之前那样写在一起,实际上会将Builder和Director自由组合,产生大量的House类,修改时会更改大量的代码,耦合度很高)

并且创建房子的步骤可能很复杂,步骤之间可能会有一些依赖关系,这时候将步骤步骤到Director里面可以使得程序逻辑更加清晰,减少出错的概率

盖房子实现

House
@Data
public class House implements Cloneable, Serializable {
    private String base;
    private String wall;
    private String roof;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

这里可以配合原型模式,这样houseDirector每调用一次build方法都会建造一个新的房子

AbstractHouseBuilder

负责设置建造的接口与设计规范,封装建造房子的通用逻辑

public abstract class AbstractHouseBuilder {
    protected House house=new House();
    abstract protected void buildBase();
    abstract protected void buildWall();
    abstract protected void buildRoof();
    public House createHouse(){
        try {
            return (House) house.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
CommonHouseBuilder

建造小房子的实现类

public class CommonHouseBuilder extends AbstractHouseBuilder{
    @Override
    protected void buildBase() {
        house.setBase("5米地基");
        System.out.println("打地基");
    }

    @Override
    protected void buildWall() {
        house.setWall("3米的墙");
        System.out.println("盖墙");
    }

    @Override
    protected void buildRoof() {
        house.setRoof("小房顶");
        System.out.println("盖房顶");
    }
}
HighHouseBuilder

盖大房子的实现类

public class HighHouseBuilder extends AbstractHouseBuilder{
    @Override
    protected void buildBase() {
        house.setBase("10米地基");
        System.out.println("打地基");
    }

    @Override
    protected void buildWall() {
        house.setWall("100米墙");
        System.out.println("搭建墙");
    }

    @Override
    protected void buildRoof() {
        house.setRoof("大房顶");
        System.out.println("盖房顶");
    }
}
HouseDirector

盖房子的指挥者,调用建造者来创建对象并交付实例对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class HouseDirector {
    private AbstractHouseBuilder houseBuilder;
    House buildHouse(){
        houseBuilder.buildBase();
        houseBuilder.buildWall();
        houseBuilder.buildRoof();
        return houseBuilder.createHouse();
    }
}
Client(调用方)

中间可以切换建造者,每次建造出的房子也都不一样

public class Client {
    public static void main(String[] args) {
        HouseDirector houseDirector=new HouseDirector(new CommonHouseBuilder());
        System.out.println(houseDirector.buildHouse());
        System.out.println(houseDirector.buildHouse());
        houseDirector.setHouseBuilder(new HighHouseBuilder());
        System.out.println(houseDirector.buildHouse());
    }
}

源码分析StringBuilder

image-20220528111039772

可以看到链式编程的思想

这里因为建造的流程本身就是不确定的,我们可以调用很多次append方法来添加字符串,所以实际的指挥者,其实是我们的业务代码。所以如果建造的流程不确定,我们应当将建造的接口暴露给Client,让Client来调用接口来建造,每一步建造都能得到建造后的结果(return this),这样也能包含建造者模式的精髓。而如果建造的过程是确定的,并且有时候会很复杂,这时候应当将建造的过程封装到Director中

image-20220528113234497

image-20220528113352615

抽象工厂模式专注于创建不同种类的对象

建造者模式则专注于创建不同属性的对象

工厂模式只负责将对象的创建过程和使用过程分离开,并不关心这个对象具体是怎么创建的,因而实际上创建对象的具体过程可以交给建造者模式来完成

建造者模式适用于建造同类的产品(属性要是一样的),如果需要创建的产品之间差异很大,可能不适合用建造者模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值