掘金 后端 ( ) • 2024-03-28 11:20

建造者模式

建造者模式也叫生成器模式,是一种用于构建对象的模式。它可以将复杂对象的构建过程抽象出来成为一个抽象类或者接口,使这个抽象的过程的不同实现方法可以构造出不同表现(具有不同属性)的子类或者这实现类对象。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节是怎么实现的。

建造者模式包含的四种角色: Product(产品角色):一个具体的产品对象。 Builder(抽象建造者):一个可以创建Product对象的各个零件的接口或者抽象类。 ConcreteBuilder(具体建造者):Builder的实现类或者子类,用于具体细节地去创建Product对象的各个零件。 Director(指挥者):内部会构建一个Builder实现类或者子类的对象,用于创建一个复杂的对象;作用其一是将用户与产品生产的过程进行了隔离,其二是可以控制产品的生产过程。

注意事项: 建造者模式是用于创建复杂的对象且这个复杂的对象的加工有一定顺序要求的。也就是说这个对象的创建是由多个零件组成的且在创建过程中组装每个零件的都是有步骤要求的。

案例:

  • 以汽车生产为例:生产和组装汽车需要的工序是:生产发动机、生产汽车外壳、将发动机组装到外壳中、生产轮胎、将轮胎组装到汽车外壳中。

  • 生产汽车的过程虽然都是一样的,但是不同配置等级的汽车对每个零件的要求是不同的。

以下案例中CarDirector类就是指挥者角色,CarBuilder类就是抽象建造者角色,StandardCarBuilder类和HighCollocationCarBuilder类就是具体的建造者角色,Car类就是具体的产品角色。

UML类图:

建造者模式.jpg

客户端Client类:

/**
 * 使用建造者模式实现的建造汽车客户端
 * 用建造者模式:将产品和产品的生产过程解耦,也就是拆分开,进行实现
 */
public class Client {
​
    public static void main(String[] args) {
        //生产标配汽车
        CarDirector carDirector = new CarDirector(new StandardCarBuilder());
        Car standardCar = carDirector.buildCar();
        System.out.println("得到的汽车是:" + standardCar);
​
        //生产高配汽车
        carDirector.setCarBuilder(new HighCollocationCarBuilder());
        Car highCollocationCar = carDirector.buildCar();
        System.out.println("得到的汽车是:" + highCollocationCar);
    }
}

汽车建造者指挥者CarDirector类:

/**
 * 汽车建造指挥者
 */
public class CarDirector {
​
    private CarBuilder carBuilder = null;
​
    public CarDirector() {
​
    }
​
    //构造器注入
    public CarDirector(CarBuilder carBuilder) {
        this.carBuilder = carBuilder;
    }
​
    //set方法注入
    public void setCarBuilder(CarBuilder carBuilder) {
        this.carBuilder = carBuilder;
    }
​
    /**
     * 将汽车的组装过程交给指挥者来控制
     */
    public Car buildCar() {
        Engine engine = carBuilder.buildEngine();
        CarShell carShell = carBuilder.buildCarShell();
        System.out.println("将" + engine + "组装到" + carShell + "中");
        Tyre tyre = carBuilder.buildTyre();
        System.out.println("将" + tyre + "组装到" + carShell + "中");
        Car car = new Car();
        car.setEngine(engine);
        car.setCarShell(carShell);
        car.setTyre(tyre);
        return car;
    }
}

汽车建造者CarBuilder接口类:

/**
 * 汽车建造者接口
 */
public interface CarBuilder {
    //生产外壳
    CarShell buildCarShell();
    //生产发动机
    Engine buildEngine();
    //生产轮胎
    Tyre buildTyre();
}

标配汽车建造者StandardCarBuilder类:

/**
 * 标配汽车建造者
 */
public class StandardCarBuilder implements CarBuilder {
​
    /**
     * 建造汽车外壳
     */
    @Override
    public CarShell buildCarShell() {
        return new CarShell("标配汽车外壳");
    }
​
    /**
     * 建造发动机
     */
    @Override
    public Engine buildEngine() {
        return new Engine("标配汽车发动机");
    }
​
    /**
     * 建造轮胎
     */
    @Override
    public Tyre buildTyre() {
        return new Tyre("标配汽车轮胎");
    }
}

高配汽车建造者HighCollocationCarBuilder类:

/**
 * 高配汽车建造者
 */
public class HighCollocationCarBuilder implements CarBuilder {
​
    /**
     * 建造汽车外壳
     */
    @Override
    public CarShell buildCarShell() {
        System.out.println("给高配汽车的外壳添加优质的钢材");
        return new CarShell("高配汽车外壳");
    }
​
    /**
     * 建造发动机
     */
    @Override
    public Engine buildEngine() {
        return new Engine("高配汽车发动机");
    }
​
    /**
     * 建造轮胎
     */
    @Override
    public Tyre buildTyre() {
        return new Tyre("高配汽车轮胎");
    }
}

汽车外壳CarShell类:

/**
 * 汽车外壳类
 */
public class CarShell {
​
    private String name;
​
    public CarShell(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return name;
    }
}

汽车发动机Engine类:

/**
 * 发动机类
 */
public class Engine {
​
    private String name;
​
    public Engine(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return name;
    }
}

汽车轮胎Tyre类:

/**
 * 轮胎类
 */
public class Tyre {
​
    private String name;
​
    public Tyre(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return name;
    }
}

汽车Car类:

/**
 * 汽车
 */
public class Car {
​
    //汽车外壳
    private CarShell carShell;
​
    //汽车发动机
    private Engine engine;
​
    //汽车轮胎
    private Tyre tyre;
​
    public CarShell getCarShell() {
        return carShell;
    }
​
    public void setCarShell(CarShell carShell) {
        this.carShell = carShell;
    }
​
    public Engine getEngine() {
        return engine;
    }
​
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
​
    public Tyre getTyre() {
        return tyre;
    }
​
    public void setTyre(Tyre tyre) {
        this.tyre = tyre;
    }
​
    @Override
    public String toString() {
        return "Car:" + carShell + "+" + engine + "+" + tyre;
    }
​
}

总结:

  • 客户端(使用方)不必知道产品内部的组成细节,将产品与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品。
  • 每一个具体的建造者都相对独立,而与其它的建造者都无关,因此可以很方便的替换具体的建造者或增加具体新的建造者,用户使用不同的建造者即可获得不同的产品以上两点遵守了单一职能原则。
  • 可以更加精细地去控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便在代码中去控制创建过程,具有很好的可读性。
  • 增加具体的建造者无需修改原有的产品类代码,指挥者类是面向抽象的建造者编程,所以具有很好的可扩展性,遵守了开闭原则和依赖倒置原则。
  • 是使用的聚合的方式代替继承,所以遵守了合成复用原则。
  • 建造者模式所创建的产品一般具有较多的共同特点,其组成部分相似,具有相似的组装步骤,如果产品之间的差异性很大,则不适合使用建造者模式。
  • 如果产品的内部变化复杂,可能会导致定义多个具体的建造者去实现变化,导致系统变得很庞大,类的复杂度大大增加,这种情况也不适用建造者模式。(如果说建造者类超过5个,那么就要考虑不使用建造者模式了)
  • 建造者模式和工厂模式的区别: 工厂模式注重的是整体对象的创建方法,而建造者模式注重的是对象的创建过程,创建对象的过程方法可以在创建时自由调用。使用工厂模式是不关心产品的构建过程的,只关心什么类型的产品由什么类型的工厂去创建,而建造者模式是要求按照指定的工序去建造产品,它的主要目的是通过组装不同的零件而产生一个新的产品。