美文网首页
创建型模型——建造者模式

创建型模型——建造者模式

作者: Doooook | 来源:发表于2020-08-16 08:56 被阅读0次

建造者模式与其他创建型模式一样服务于相同的目标,只不过它出于不同的原因,通过不同的方式实现。在开发复杂的应用程序时,代码往往会变得非常复杂。类会封装更多的功能,类的结构也会变得更加复杂。随着功能量的增加,就需要涵盖更多场景,从而需要构建更多不同的类。
当需要实例化一个复杂的类,以得到不同结构和不同内部状态的对象时,我们可以使用不同的类对它们的实例化操作逻辑分别进行封装,这些类就被称为建造者。每当需要来自同一个类但具有不同结构的对象时,就可以通过构造另一个建造者来进行实例化。

image.png
建造者模式中包含以下类:
  • Product(产品类):需要为其构建对象的类,是具有不同表现形式的复杂或复合对象。
  • Builder(抽象建造者类):用于声明构建产品类的组成部分的抽象类或接口。它的作用是仅公开构建产品类的功能,隐藏产品类的其他功能;将产品类与构建产品类的更高级的类分离开。
  • ConcreteBuilder(具体建造者类:用于实现抽象建造者类接口中声明的方法。除此之外,它还通过getResult方法返回构建好的产品类。
  • Director(导演类):用于指导如何构建对象的类。在建造者模式的某些变体中,导演类已被移除,其角色被客户端或抽象建造者类所代替。

汽车建造者样例

存在一个Car类,需要为它创建实例。通过向汽车中添加不同的组件,我们分别可以制造燃油车纯电车混动车等。当开始设计软件时,需要认识到以下几点:

  • Car类非常复杂,创建类的对象也是一个复杂的操作。在Car类的构造函数中添加所有的实例化逻辑将使其变得体量庞大。
  • 我们需要构建多种类型的汽车类。针对这种情况,我们通常会添加多个不同的构造函数,但直觉告诉我们这并非最好的解决方案。
  • 将来我们可能需要构建多种不同类型的汽车对象。由于市场上对于混动车的需求非常高涨,在不久的将来,我们应该做好准备进行代码扩展而不是重新修改代码。
    AbstractCarBuilder是建造者基类,我们创建了两个具体建造者类:ElectricCarBuilderGasolineCarBuilder。每个建造者实现类都分别实现了AbstractCarBuilder的所有抽象方法。那些类中不需要的方法(例如ElectricCarBuilder中的addGasTank方法)会被置空或抛出异常。ElectricCar类和GasolineCar类内部结构是不同的。
/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:37
 * @description: 抽象构建者
 */
public abstract class AbstractCarBuilder {

    /**
     * 构建一个无参的BCar
     * @return
     */
    public abstract void buildCar();

    /**
     * 设置发动机类型
     * @param engineType
     */
    public abstract void setEngineType(String engineType);

    /**
     * 设置轮胎类型
     * @param wheelType
     */
    public abstract void setWheelType(String wheelType);

    /**
     * 设置颜色
     * @param color
     */
    public abstract void setColor(String color);

    /**
     * 设置传动方式,手动、自动
     * @param transmission
     */
    public abstract void setTransmission(String transmission);

    /**
     * 汽油车加汽油
     * @param capacity
     */
    public abstract void addGasTank(String capacity);

    /**
     * 新能源车加电池
     * @param capacity
     */
    public abstract void addBatteries(String capacity);

    /**
     * 返回构建的BCar
     * @return BCar
     */
    public abstract BCar getCar();

}
/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:37
 * @description: 燃油车
 */
public class GasolineCarBuilder extends AbstractCarBuilder {

    private BCar bCar;

    @Override
    public void buildCar() {
        this.bCar = new BCar();
    }

    @Override
    public void setEngineType(String engineType) {
        this.bCar.setEngineType(engineType);
    }

    @Override
    public void setWheelType(String wheelType) {
        this.bCar.setWheelType(wheelType);
    }

    @Override
    public void setColor(String color) {
        this.bCar.setColor(color);
    }

    @Override
    public void setTransmission(String transmission) {
        this.bCar.setTransmission(transmission);
    }

    @Override
    public void addGasTank(String capacity) {
        this.bCar.setGasTank(capacity);
    }

    @Override
    public void addBatteries(String capacity) {
        throw new RuntimeException("燃油车不能加电池!");
    }

    @Override
    public BCar getCar() {
        return this.bCar;
    }

}
/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:37
 * @description: 纯电车
 */
public class ElectricCarBuilder extends AbstractCarBuilder {

    private BCar bCar;

    @Override
    public void buildCar() {
        this.bCar = new BCar();
    }

    @Override
    public void setEngineType(String engineType) {
        this.bCar.setEngineType(engineType);
    }

    @Override
    public void setWheelType(String wheelType) {
        this.bCar.setWheelType(wheelType);
    }

    @Override
    public void setColor(String color) {
        this.bCar.setColor(color);
    }

    @Override
    public void setTransmission(String transmission) {
        this.bCar.setTransmission(transmission);
    }

    @Override
    public void addGasTank(String capacity) {
        throw new RuntimeException("纯电车不能加油!");
    }

    @Override
    public void addBatteries(String capacity) {
        this.bCar.setBatteries(capacity);
    }

    @Override
    public BCar getCar() {
        return this.bCar;
    }
    
}

导演类使用抽象建造者类来创建新的汽车对象。buildElectricCarbuildGasolineCar两个方法略有不同:

/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:37
 * @description:
 */
public class CarBuilderDirector {

    public BCar buildElectricCar(AbstractCarBuilder carBuilder) {
        carBuilder.buildCar();
        carBuilder.setEngineType("Nio");
        carBuilder.setWheelType("Michelin");
        carBuilder.setColor("Green");
        carBuilder.setTransmission("Auto");
        // 会抛异常:纯电车不能加油
        // carBuilder.addGasTank("Nio gasTank");
        carBuilder.addBatteries("Nio batteries");
        return carBuilder.getCar();
    }

    public BCar buildGasolineCar(AbstractCarBuilder carBuilder) {
        carBuilder.buildCar();
        carBuilder.setEngineType("BYD");
        carBuilder.setWheelType("Good Year");
        carBuilder.setColor("Gray");
        carBuilder.setTransmission("Manual");
        carBuilder.addGasTank("BYD gasTank");
        // 会抛异常:燃油车不能加电池
        // carBuilder.addBatteries("BYD batteries");
        return carBuilder.getCar();
    }

}

如果想要制造一辆既有电动又有汽油发动机的混合动力汽车,扩展一个HybridCarBuilder

/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:37
 * @description: 混动车
 */
public class HybridCarBuilder extends AbstractCarBuilder {

    private BCar bCar;

    @Override
    public void buildCar() {
        this.bCar = new BCar();
    }

    @Override
    public void setEngineType(String engineType) {
        this.bCar.setEngineType(engineType);
    }

    @Override
    public void setWheelType(String wheelType) {
        this.bCar.setWheelType(wheelType);
    }

    @Override
    public void setColor(String color) {
        this.bCar.setColor(color);
    }

    @Override
    public void setTransmission(String transmission) {
        this.bCar.setTransmission(transmission);
    }

    @Override
    public void addGasTank(String capacity) {
        // 混动车既可以加油也可以加电池
        this.bCar.setGasTank(capacity);
    }

    @Override
    public void addBatteries(String capacity) {
        // 混动车既可以加油也可以加电池
        this.bCar.setBatteries(capacity);
    }

    @Override
    public BCar getCar() {
        return this.bCar;
    }
    
}

导演类添加buildHybridCar方法:

public BCar buildHybridCar(AbstractCarBuilder carBuilder) {
      carBuilder.buildCar();
      carBuilder.setEngineType("TOYOTA");
      carBuilder.setWheelType("Continental AG");
      carBuilder.setColor("White");
      carBuilder.setTransmission("Auto");
      carBuilder.addGasTank("Toyota gasTank");
      carBuilder.addBatteries("Tesla batteries");
      return carBuilder.getCar();
}

测试:

    /**
     * 创建型模式——建造者模式1
     */
    @Test
    public void testBuilder1() {
        CarBuilderDirector carBuilderDirector = new CarBuilderDirector();

        ElectricCarBuilder electricCarBuilder = new ElectricCarBuilder();
        BCar electricCar = carBuilderDirector.buildElectricCar(electricCarBuilder);
        System.out.println(JSON.toJSONString(electricCar));

        GasolineCarBuilder gasolineCarBuilder = new GasolineCarBuilder();
        BCar gasolineCar = carBuilderDirector.buildGasolineCar(gasolineCarBuilder);
        System.out.println(JSON.toJSONString(gasolineCar));

        HybridCarBuilder hybridCarBuilder = new HybridCarBuilder();
        BCar hybridCar = carBuilderDirector.buildHybridCar(hybridCarBuilder);
        System.out.println(JSON.toJSONString(hybridCar));
    }

拥有方法链的匿名建造者

构建来自相同类但具有不同形式的对象的最直接方法就是构建多个构造函数,按照不同的场景进行不同的实例化操作。使用建造者模式避免这种情况是个不错的实践,在《EffectiveJava》一书中,Joshua Bloch建议使用内部建造者类和方法链来代替构建多个构造函数。
方法链是指通过特定方法返回当前对象(this)的一种技术。通过这种技术,可以以链的形式调用方法。

package com.mitter.book.review.designpattern.builder;

import lombok.Data;

/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:39
 * @description:
 */
@Data
public class CCar {
    /**
     * 发动机类型,共享
     */
    private String engineType;
    /**
     * 轮胎类型,共享
     */
    private String wheelType;
    /**
     * 颜色,共享
     */
    private String color;
    /**
     * 变速箱,共享
     */
    private String transmission;
    /**
     * 油箱,燃油车
     */
    private String gasTank;
    /**
     * 电池,纯电车
     */
    private String batteries;

    /**
     * 内部类方法链的匿名建造者
     */
    public static class Builder {
        private CCar cCar = new CCar();
        public Builder setEngineType(String engineType) {
            cCar.setEngineType(engineType);
            return this;
        }
        public Builder setWheelType(String wheelType) {
            cCar.setWheelType(wheelType);
            return this;
        }
        public Builder setColor(String color) {
            cCar.setColor(color);
            return this;
        }
        public Builder setTransmission(String transmission) {
            cCar.setTransmission(transmission);
            return this;
        }
        public Builder setGasTank(String gasTank) {
            cCar.setGasTank(gasTank);
            return this;
        }
        public Builder setBatteries(String batteries) {
            cCar.setBatteries(batteries);
            return this;
        }
        public CCar build() {
            return this.cCar;
        }
    }

}

测试:

    /**
     * 创建型模式——建造者模式3
     */
    @Test
    public void testBuilder3() {
        CCar cCar = new CCar.Builder().setEngineType("BMW")
                .setWheelType("Michelin")
                .setColor("Red")
                .setTransmission("Auto")
                .setGasTank("60L")
                .setBatteries("300 kwh")
                .build();
        System.out.println(cCar);
    }

使用Lombok@Builder注解实现链式构建者模式:

/**
 * @author: Jay Mitter
 * @date: 2020-08-15 10:39
 * @description:
 */
@Data
@Builder
public class DCar {
    /**
     * 发动机类型,共享
     */
    private String engineType;
    /**
     * 轮胎类型,共享
     */
    private String wheelType;
    /**
     * 颜色,共享
     */
    private String color;
    /**
     * 变速箱,共享
     */
    private String transmission;
    /**
     * 油箱,燃油车
     */
    private String gasTank;
    /**
     * 电池,纯电车
     */
    private String batteries;

}

测试:

    /**
     * 创建型模式——建造者模式4
     */
    @Test
    public void testBuilder4() {
        DCar dCar = DCar.builder().engineType("Benz")
                .wheelType("Good Year")
                .color("Black")
                .transmission("Manual")
                .gasTank("58L")
                .batteries("350 KWH")
                .build();
        System.out.println(dCar);
    }

相关文章

  • 建造者设计模式-Builder design pattern

    建造者设计模式是创建型设计模式的一种。创建型设计模式处理对象创建的问题。 建造者设计模式,用来构建需要经过若干个建...

  • 设计模式之创建型

    创建型指的是对象模型的创建。 有以下五种方式: 单例、原型、工厂、抽象工厂、建造者。 单例有懒汉模式和饿汉模式,区...

  • 建造者模式

    建造者模式 创建型模式 Director、Builder、Product建造模型 Builder负责构建Produ...

  • 设计模式-构建者模式

    概念 建造者模式(英:Builder Pattern)是一种创建型设计模式,又名:生成器模式。GOF 给建造者模式...

  • 设计模式概要

    创建型模式:工厂模型,抽象工厂模型,建造模型,原型模型,单例模型,结构型模式:适配器,桥,组合模型,行为型设计模式...

  • PHP常用设计模式

    # 创建型 单例模式 工厂模式 工厂抽象模式 原型模式 建造者模式 # 结构型 # 行为型 # 3.注册模式 # ...

  • 23天学习23种设计模式——建造者模式

    是什么——什么是建造者模式 建造者模式(Builder Pattern),是一种对象创建型设计模式。它将一个复杂对...

  • 建造者模式(创建型)

    建造者模式[https://www.runoob.com/design-pattern/builder-patte...

  • 建造者模式——创建型

    定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 用户只需要指定需要建造的类型就可以...

  • 设计模式之建造者模式

    设计模式之建造者模式 Intro 简介 建造者模式: 建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加...

网友评论

      本文标题:创建型模型——建造者模式

      本文链接:https://www.haomeiwen.com/subject/qcoodktx.html