设计模式那些事儿

设计模式详解之建造者模式

2020-07-07  本文已影响0人  CryFace

建造者模式属于创建型模式,提供了一种创建对象的最佳方式。

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。

建造者模式的四个对象

Product产品类:

通常是实现了模板方法模式(这里可以后续看我的更新博客,如果我更新了),也就是有模板方法和基本方法。

Builder抽象建造者:

规范产品的组建,一般是由子类实现。

ConcreteBuilder具体建造者:

实现抽象类定义的所有方法,并且返回一个组建好的对象。

Director导演类:

负责安排已有模块的顺序,然后告诉Builder开始建造。

例子

举个例子:

同样的,我们以这个例子用代码来实现一下更能清晰的了解。

我们的汽车类(Car),也就是我们的产品

package builder;

public abstract class Builder {
    private String wheel;  //车轮
    private String carDoor; //车门
    private String engine;  //发动机
    private String steeringWheel;  //方向盘

    ...我们的get和set方法(为了简洁,我就不展示了)...

    @Override
    public String toString() {
        return "Builder{" +
                "wheel='" + wheel + '\'' +
                ", carDoor='" + carDoor + '\'' +
                ", engine='" + engine + '\'' +
                ", steeringWheel='" + steeringWheel + '\'' +
                '}';
    }
}

我们的建造抽象类(Builder

package builder;

public abstract class Builder {

    abstract void buildWheel(); //建造车轮
    abstract void buildCarDoor(); //建造车门
    abstract void buildEngine(); //建造发动机
    abstract void buildSteeringWheel(); //建造方向盘

    //建造完成,获得车辆
    abstract Car getCar();
}

我们的建造实现类(ConcreteBuilder

package builder;

public class ConcreteBuilder extends Builder{

    private Car car;

    //定义一个空构造方法,在实例化的同时实例我们的车
    public ConcreteBuilder(){
        car = new Car();
    }

    @Override
    void buildWheel() {
        car.setWheel("轮子");
    }

    @Override
    void buildCarDoor() {
        car.setCarDoor("车门");
    }

    @Override
    void buildEngine() {
        car.setEngine("发动机");
    }

    @Override
    void buildSteeringWheel() {
        car.setSteeringWheel("方向盘");
    }

    @Override
    Car getCar() {
        return car;
    }
}

我们的导演类(Director),用来指挥我们的创建过程,比如创建顺序

package builder;

public class Director {

    public Car carBuilder(Builder builder){
        //按照我们的导演的顺序来创建车辆
        builder.buildWheel();
        builder.buildCarDoor();
        builder.buildEngine();
        builder.buildSteeringWheel();
        
        //创建完之后,返回我们创建完的车辆
        return builder.getCar();
    }

}

我们在测试类中测试一下

package builder;

public class Test {

    public static void main(String[] args) {

        //创建一个我们的导演,指挥
        Director director = new Director();
        //导演指挥我们具体的实现类去创建车辆
        Car car = director.carBuilder(new ConcreteBuilder());
        System.out.println(car.toString());
    }

}


//测试结果
Car{wheel='轮子', carDoor='车门', engine='发动机', steeringWheel='方向盘'}
Process finished with exit code 0

可以看到,通过这样的建造者模式,我们的复杂过程被我们封装了起来。但是我们也发现了我们的导演可以指挥顺序,但是里面具体的参数,比如想建造什么无法修改。其实也可以,我们对导演类进行扩展一下就行。

我们通过静态内部类实现零件无序装配构造,这种方式使用更加灵活,更符合定义。使用的时候可以根据用户需求自定义更改内容。我们对其修改后,示例代码如下:

我们对抽象建造的抽象方法添加了传递参数,修改了返回类型

package builder;

public abstract class Builder {

    abstract Builder buildWheel(String msg); //建造车轮
    abstract Builder buildCarDoor(String msg); //建造车门
    abstract Builder buildEngine(String msg); //建造发动机
    abstract Builder buildSteeringWheel(String msg); //建造方向盘

    //建造完成,获得车辆
    abstract Car getCar();
}

然后在实现类进行实现

package builder;

public class ConcreteBuilder extends Builder{

    private Car car;

    //定义一个空构造方法,在实例化的同时实例我们的车
    public ConcreteBuilder(){
        car = new Car();
    }

    @Override
    Builder buildWheel(String msg) {
        car.setWheel(msg);
        return this;
    }

    @Override
    Builder buildCarDoor(String msg) {
        car.setCarDoor(msg);
        return this;
    }

    @Override
    Builder buildEngine(String msg) {
        car.setEngine(msg);
        return this;
    }

    @Override
    Builder buildSteeringWheel(String msg) {
        car.setSteeringWheel(msg);
        return this;
    }

    @Override
    Car getCar() {
        return car;
    }
}

这时我们在导演类里面,就可以自由的传递我们需要的参数来建造车辆,也可以指定顺序。

package builder;

public class Director {

    public Car carBuilder(Builder builder){
        //创建自定义车辆,自定义建造顺序
        return builder.buildWheel("厉害的车轮")
                .buildCarDoor("漂亮的车门")
                .buildEngine("马力十足的引擎")
                .buildSteeringWheel("舒服的方向盘")
                .getCar();
    }

}

测试类的测试结果

Car{wheel='厉害的车轮', carDoor='漂亮的车门', engine='马力十足的引擎', steeringWheel='舒服的方向盘'}

Process finished with exit code 0

总结

建造者模式关注的是零件类型和装配顺序,我们可以总结一下它的优缺点和使用场景。

优点:

缺点:

差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

使用场景:

补充:

通过学习建造者模式,我们可以发现这与我们的抽象工厂模式很是相像,但是也是有不同的地方。(关于工厂模式可以看我的设计模式详解之工厂模式

建造者模式最主要的功能是基本方法的调用顺序安排,因为组装顺序不同对象效能也不同,这才是建造者模式要表达的核心意义。

参考资料

(书籍)大话设计模式

(视频)遇见狂神说:通俗易懂的23种设计模式教学

上一篇下一篇

猜你喜欢

热点阅读