建造者模式介绍

该模式主要用于对象的创建,多用于创建具有复杂结构的对象。核心的思路是将产品本身的生产过程进行拆分,将复杂对象的构造过程与最终表现形式进行分离。

这么做有两点好处

  1. 将产品的结构和产品的零件的建造过程对客户端隐藏起来,用户可以轻松的调用对应的构造方法构造出需要的复杂对象
  2. 较好的实现代码的封装与服用,可以通过产品内部不同构造方法的组合使用来构造出自定义的产品对象

具体的建造者模式的实现方式大体上分为两种

  1. 通过Client、Director、Builder和Product形成的建造者模式,用于保证有序的创造产品
  2. 去掉Director,由用户来选择构造顺序的无序可组合构造

第一种建造者模式

一般有以下四个角色

抽象建造者(builder):描述具体建造者的公共接口,一般用来定义建造细节的方法,并不涉及具体的对象部件的创建。

具体建造者(ConcreteBuilder):描述具体建造者,并实现抽象建造者公共接口。

指挥者(Director):调用具体建造者来创建复杂对象(产品)的各个部分,并按照一定顺序(流程)来建造复杂对象。

产品(Product):描述一个由一系列部件组成较为复杂的对象。

以KFC中的汉堡制作为例,这里简单化处理,假设KFC的汉堡制作主要分为准备蔬菜,烤肉饼,组装

抽象建造者,用来定义方法

//建造模式
public abstract class Builder {
    //准备蔬菜
    public abstract void prepareVegetable();
    //烤肉饼
    public abstract void meatloaf();
    //制作
    public abstract void make();
}

产品(汉堡)

@Data
public class Hamburg {
    private String prepareVegetable;
    private String meatloaf;
    private String make;
    @Override
    public String toString() {
        return prepareVegetable+"\n"+meatloaf+"\n"+make+"\n";
    }
}

具体建造者

@Data
public class ConcreteBuilder extends Builder{
    private Hamburg hamburg;

    public  ConcreteBuilder()
    {
        hamburg=new Hamburg();
    }
    @Override
    public void prepareVegetable() {
        hamburg.setPrepareVegetable("蔬菜准备完成");
    }

    @Override
    public void meatloaf() {
        hamburg.setMeatloaf("烤肉饼准备完成");
    }

    @Override
    public void make() {
        hamburg.setMake("汉堡制作完成");
    }

}

指挥者

public class Director {
    public Hamburg create()
    {
        ConcreteBuilder concreteBuilder=new ConcreteBuilder();
        concreteBuilder.prepareVegetable();
        concreteBuilder.meatloaf();
        concreteBuilder.make();
        Hamburg hamburg = concreteBuilder.getHamburg();
        return hamburg;
    }
}

具体的逻辑大致如下

  1. 指挥者创建实际建造者按照指挥者规定的顺序来建造产品
  2. 实际建造者根据抽象建造者中的方法针对对应的产品实现对应的方法
  3. 实际建造者完成指挥者规定的建造流程后返回产品对象

第二种建造者模式

这个模式下我们去掉指挥者的角色,将建造流程交给用户自己选择,这种方法对于用户来说更加灵活,用户可以根据需求自定义产品的内容。

继续以KFC为例,在KFC中存在多种商品,用户点单的时候可以自由的选择自己需要的商品。
我们将一个用户的一次订单看作一个产品,则每一个商品都可以认为是产品的组件之一,故可以使用建造者模式。

产品类(订单)

@Data
public class Order {
    private String hamburg;
    private String frenchFries;
    private String friedChicken;
    @Override
    public String toString() {
        String str="";
        if(hamburg!=null){
            str+=hamburg+"\n";
        }
        if(frenchFries!=null){
            str+=frenchFries+"\n";
        }
        if(friedChicken!=null){
            str+=friedChicken+"\n";
        }
        return str;
    }
}

抽象建造者

public abstract class OrderBuilder {
    //汉堡
    public abstract OrderBuilder hamburg();
    //薯条
    public abstract OrderBuilder frenchFries();
    //炸鸡
    public abstract OrderBuilder friedChicken();
    public abstract Order getOrder();
}

具体建造者

public class OrderConcreteBuilder extends OrderBuilder{
    private Order order;
    public OrderConcreteBuilder()
    {
        order=new Order();
    }
    @Override
    public OrderBuilder hamburg() {
        order.setHamburg("用户添加汉堡");
        return this;
    }

    @Override
    public OrderBuilder frenchFries() {
        order.setFrenchFries("用户添加薯条");
        return this;
    }

    @Override
    public OrderBuilder friedChicken() {
        order.setFriedChicken("用户添加炸鸡");
        return this;
    }

    @Override
    public Order getOrder() {
        return order;
    }
}

测试类

   @Test
    public void UserBuildTest()
    {
        //用户点炸鸡和薯条
        OrderConcreteBuilder orderConcreteBuilder=new OrderConcreteBuilder();
        Order order = orderConcreteBuilder.frenchFries().friedChicken().getOrder();
        System.out.println(order);
        //用户点汉堡和炸鸡
        OrderConcreteBuilder orderConcreteBuilder1=new OrderConcreteBuilder();
        Order order1 = orderConcreteBuilder1.hamburg().friedChicken().getOrder();
        System.out.println(order1);
    }

测试结果

用户添加薯条
用户添加炸鸡

用户添加汉堡
用户添加炸鸡

总结

通过上述例子可以看出建造者模式主要适合以下的一些应用场景

  1. 生成的对象具有复杂的内部结构,存在多个对象具有相似的细节
  2. 需要创建的对象有着复杂且固定的创建流程
  3. 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐