设计模式 | 建造者模式

知识点五: 建造者模式


一、概述

建造者模式(Builder Pattern),又被称为生成器模式,它属于23种GOF设计模式的创建型设计模式 ,它与工厂方法模式抽象工厂模式不同,后两者的目的是为了实现多态性,而 建造者模式的目的则是为了将对象的构建与展示分离建造者模式是使用多个简单的对象一步一步构建成一个复杂的对象。 它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。一个复杂的对象有大量的组成部分,比如汽车它有车轮、方向盘、发动机、以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过程无疑会复杂,对于这种情况,为了实现在构建过程中对外部隐藏具体细节,就可以使用 Builder 模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,同时也能够将两者之间的耦合降到最低。

该模式用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。


二、优缺点及使用场景

优点:

  • 建造者独立,易扩展。
  • 便于控制细节风险。

缺点:

  • 产品必须有共同点,范围有限制。
  • 如内部变化复杂,会有很多的建造类。

使用场景

  • 对象的创建:Builder模式是为对象的创建而设计的模式
  • 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
  • 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法

三、模式中包含的角色和其职责以及模式实现方式

1、角色

抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

具体建造者(ConcreteBuilder)角色:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

监工(Director)角色:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

具体产品(Product)角色:要创建的复杂对象。

2、实现方式

建造者:创建和提供实例

监工:管理建造出来的实例的依赖关系。

建造者模式.png


四、在Java中的实现

1、抽象建造者

/**
 * @Description: 抽象建造者
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 20:03
 */
public interface HouseBuilder {
    //建地板
    public void buildFloor();
    //建墙
    public void buildWall();
    //建屋顶
    public void buildHousetop();
    //交付(返回对象)
    public House getProduct();
}

2、具体建造者

/**
 * @Description: 修平房的工程队
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 20:06
 */
public class PingFangBuilder implements HouseBuilder {
    //修房子就要给个房子实例
    House house = new House();

    //房子(类)具体属性给各个建造工人(方法)去赋值
    @Override
    public void buildFloor() {
        house.setFloor("平房---地板");
    }

    @Override
    public void buildWall() {
        house.setWall("平房---墙");
    }

    @Override
    public void buildHousetop() {
        house.setHousetop("平房---屋顶");
    }

    @Override
    public House getProduct() {
        return house;
    }
}

3、监工

/**
 * @Description: 监工
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 20:20
 */
public class HouseDirector {
    private HouseBuilder builder;

    //使用构造给工程队赋值
    public HouseDirector(HouseBuilder builder){
        this.builder = builder;
    }

    //监工让工程队建房子
    public void makeHouse(){
        builder.buildFloor();
        builder.buildHousetop();
        builder.buildWall();
    }
    /* 大部分人都这么写,省资源
    public void makeHouse(HouseBuilder builder){
        builder.buildFloor();
        builder.buildHousetop();
        builder.buildWall();
    }*/
}

4、具体产品

/**
 * @Description: 房子
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 19:54
 */
public class House {
    //地板
    private String floor;
    //墙
    private String wall;
    //屋顶
    private String housetop;

    //提供set/get方法
    public String getFloor() {
        return floor;
    }

    public void setFloor(String floor) {
        this.floor = floor;
    }

    public String getWall() {
        return wall;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getHousetop() {
        return housetop;
    }

    public void setHousetop(String housetop) {
        this.housetop = housetop;
    }

    //方便看
    @Override
    public String toString() {
        return "House{" +
                "floor='" + floor + '\'' +
                ", wall='" + wall + '\'' +
                ", housetop='" + housetop + '\'' +
                '}';
    }
}

5、客户端

/**
 * @Description: 客户端
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 19:54
 */
public class MainClass {
    /*public static void main(String[] args) {
        //工程队来建房子
        //实例化工程队
        HouseBuilder pingFangBuilder = new PingFangBuilder();
        //建房子 这里的还是客户让工程队来建 不方便 所以我们加入一个监工
        pingFangBuilder.buildFloor();
        pingFangBuilder.buildWall();
        pingFangBuilder.buildHousetop();
        //返回房子
        House house = pingFangBuilder.getProduct();
        System.out.println(house);
    }*/

    //有监工的方法
    public static void main(String[] args) {
        //先来一个工程队
        HouseBuilder pingFangBuilder = new PingFangBuilder();
        //在来一个监工,把工程队给监工管理
        HouseDirector director = new HouseDirector(pingFangBuilder);
        //监工让工程队建房子
        director.makeHouse();
        //工程队交付房子
        House product = pingFangBuilder.getProduct();
        System.out.println(product);
    }
}

结果:

结果一.png

这时候我们要改需求,我们要建别墅,那么我们只要添加一个具体建造者

/**
 * @Description: 这时候要想建别墅(新对象),只要换个建造者就好了
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 20:30
 */
public class BieShuBuilder implements HouseBuilder {
    House bieshu = new House();

    @Override
    public void buildFloor() {
        bieshu.setFloor("别墅--地板");
    }

    @Override
    public void buildWall() {
        bieshu.setWall("别墅--墙");
    }

    @Override
    public void buildHousetop() {
        bieshu.setHousetop("别墅--屋顶");
    }

    @Override
    public House getProduct() {
        return bieshu;
    }
}

修改客户端的一行代码

/**
 * @Description: 客户端
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/7 19:54
 */
public class MainClass {
    /*public static void main(String[] args) {
        //工程队来建房子
        //实例化工程队
        HouseBuilder pingFangBuilder = new PingFangBuilder();
        //建房子 这里的还是客户让工程队来建 不方便 所以我们加入一个监工
        pingFangBuilder.buildFloor();
        pingFangBuilder.buildWall();
        pingFangBuilder.buildHousetop();
        //返回房子
        House house = pingFangBuilder.getProduct();
        System.out.println(house);
    }*/

    //有监工的方法
    /*public static void main(String[] args) {
        //先来一个工程队
        HouseBuilder pingFangBuilder = new PingFangBuilder();
        //在来一个监工,把工程队给监工管理
        HouseDirector director = new HouseDirector(pingFangBuilder);
        //监工让工程队建房子
        director.makeHouse();
        //工程队交付房子
        House product = pingFangBuilder.getProduct();
        System.out.println(product);
    }*/

    //新需求,建别墅
    public static void main(String[] args) {
        //我们只需换个工程队就好了
        BieShuBuilder bieshuBuilder = new BieShuBuilder();
        //在来一个监工,把工程队给监工管理
        HouseDirector director = new HouseDirector(bieshuBuilder);
        //监工让工程队建房子
        director.makeHouse();
        //工程队交付房子
        House product = bieshuBuilder.getProduct();
        System.out.println(product);
    }
}

结果

结果二.png


转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦