深入理解设计模式之建造者模式

老大突然拉住我,喜滋滋地告诉我:“公司很满意我们做的模型,又签订了一个合同,把奔驰、宝马的车辆模型都交给我们公司制作了,不过这次额外增加了一个新需求:汽车的启动、停止、喇叭声音、引擎声音都由客户自己控制,想什么顺序就什么顺序”

那我们开始设计,来看一下类图:

类图比较简单,在CarModel中我们定义了一个setSequence方法,车辆模型的这几个动作 要如何排布,是在这个ArrayList中定义的。然后run()方法根据sequence定义的顺序完成指定 的顺序动作。我们来看模型抽象类代码:

public abstract class CarModel {
    //这个参数是各个基本方法执行的顺序
    private ArrayList<String> sequence = new ArrayList<>();

    //开始跑了
    protected abstract void start();

    //能停下来
    protected abstract void stop();

    //喇叭会出声音
    protected abstract void alarm();

    //引擎会轰隆隆地响
    protected abstract void engineBoom();

    //模型会跑
    final public void run() {
        //循环一边,谁在前,就先执行谁
        for (String actionName : this.sequence) {
            if (actionName.equalsIgnoreCase("start")) {
                this.start(); //启动汽车
            } else if (actionName.equalsIgnoreCase("stop")) {
                this.stop(); //停止汽车
            } else if (actionName.equalsIgnoreCase("alarm")) {
                this.alarm(); //喇叭开始叫了
            } else if (actionName.equalsIgnoreCase("engine boom")) {
                //引擎开始轰鸣
                this.engineBoom();
            }
        }
    }

    //把传递过来的值传递到类内
    final public void setSequence(ArrayList<String> sequence) {
        this.sequence = sequence;
    }
}

奔驰模型代码:

public class BenzModel extends CarModel {
    
    protected void alarm() {
        System.out.println("奔驰车的喇叭声音是这个样子的...");
    }

    protected void engineBoom() {
        System.out.println("奔驰车的引擎是这个声音的...");
    }

    protected void start() {
        System.out.println("奔驰车跑起来是这个样子的...");
    }

    protected void stop() {
        System.out.println("奔驰车应该这样停车...");
    }
}

宝马模型代码: 

public class BWMModel extends CarModel {
    protected void alarm() {
        System.out.println("宝马车的喇叭声音是这个样子的...");
    }

    protected void engineBoom() {
        System.out.println("宝马车的引擎是这个声音的...");
    }

    protected void start() {
        System.out.println("宝马车跑起来是这个样子的...");
    }

    protected void stop() {
        System.out.println("宝马车应该这样停车...");
    }
}

Client场景类:

class Client{
    public static void main(String[] args) {
        BenzModel benzModel = new BenzModel();
        //存放run的顺序
        ArrayList<String> sequence = new ArrayList<>();
        sequence.add("engine boom");
        sequence.add("start");
        sequence.add("stop");
        //执行顺序赋予奔驰车
        benzModel.setSequence(sequence);
        benzModel.run();
    }
}

运行结果如下:

我们只满足了一个需求,还有下一个需求呀,然后是第二个宝马模型,只要启动、停止,其他的什么都不要;第三个模型,先喇叭,然后启动,然 后停止;第四个......直到把你逼疯为止,那怎么办?我们就一个一个地来写场景类满足吗? 不可能了,那我们要想办法来解决这个问题,有了!我们为每种模型产品模型定义一个建造者,你要啥顺序直接告诉建造者,由建造者来建造。

 抽象汽车组装者:

public abstract class CarBuilder {
    
    //建造一个模型,你要给我一个顺序要求,就是组装顺序
    public abstract void setSequence(ArrayList<String> sequence); 
    //设置完毕顺序后,就可以直接拿到这个车辆模型
    public abstract CarModel getCarModel();
    
}

奔驰车组装者:

public class BenzBuilder extends CarBuilder {
    private BenzModel benz = new BenzModel();

    public CarModel getCarModel() {
        return this.benz;
    }

    public void setSequence(ArrayList<String> sequence) {
        this.benz.setSequence(sequence);
    }
}

宝马车组装者:

public class BWMBuilder extends CarBuilder {
    private BWMModel bmw = new BWMModel();

    public CarModel getCarModel() {
        return this.bmw;
    }

    public void setSequence(ArrayList<String> sequence) {
        this.bmw.setSequence(sequence);
    }
}

修改后的场景类:

class Client {
    public static void main(String[] args) {
        ArrayList<String> sequence = new ArrayList<String>();
        //客户要求,run时候时候先发动引擎
        sequence.add("engine boom");
        //启动起来
        sequence.add("start");
        //开了一段就停下来
        sequence.add("stop");
        BenzBuilder benzBuilder = new BenzBuilder();
        benzBuilder.setSequence(sequence);
        CarModel carModel = benzBuilder.getCarModel();
        carModel.run();

    }
}

我们在做项目时,经常会有一个共识:需求是无底洞,是无理性的,不可能你告诉它不增加需求就不增加,这4个过程(start、stop、alarm、engine boom)按照排列组合有很多种,公司可以随意组合,它要什么顺序的车模我就必须生成什么顺序的 车模,客户可是上帝!那我们不可能预知他们要什么顺序的模型呀,怎么办?封装一下,找 一个导演,指挥各个事件的先后顺序,然后为每种顺序指定一个代码,你说一种我们立刻就 给你生产处理,好方法,厉害!我们先修改一下类图

public class Director {
    private ArrayList<String> sequence = new ArrayList();
    private BenzBuilder benzBuilder = new BenzBuilder();
    private BWMBuilder bmwBuilder = new BWMBuilder();

    /*
     * A类型的奔驰车模型,先start,然后stop,其他什么引擎、喇叭一概没有
     */
    public BenzModel getABenzModel() {
        this.sequence.clear();
        //ABenzModel的执行顺序
        this.sequence.add("start");
        this.sequence.add("stop");
        //按照顺序返回一个奔驰车 
        this.benzBuilder.setSequence(this.sequence);
        return (BenzModel) this.benzBuilder.getCarModel();
    }
    
    /*
     * B型号的奔驰车模型,是先发动引擎,然后启动,然后停止,没有喇叭
     */
    public BenzModel getBBenzModel() {
        this.sequence.clear();
        this.sequence.add("engine boom");
        this.sequence.add("start");
        this.sequence.add("stop");
        this.benzBuilder.setSequence(this.sequence);
        return (BenzModel) this.benzBuilder.getCarModel();
    }

    public BWMModel getCBMWModel() {
        this.sequence.clear();
        this.sequence.add("alarm");
        this.sequence.add("start");
        this.sequence.add("stop");
        this.bmwBuilder.setSequence(this.sequence);
        return (BWMModel) this.bmwBuilder.getCarModel();
    } 
    
    /*
     * D类型的宝马车只有一个功能,就是跑,启动起来就跑,永远不停止
     */
    public BWMModel getDBMWModel() {
        this.sequence.clear();
        this.sequence.add("start");
        this.bmwBuilder.setSequence(this.sequence);
        return (BWMModel) this.benzBuilder.getCarModel();
    }
}

顺便说一下,大家看一下程序中有很多this调用。如果你要调用类中的成员变量或方法,需要在前面加上this关键字,不加也能正常地跑起来,但是不清晰,加上this关键字,我就是要调用本类中的成员变量或方法,而不是本方法中的一个变量。还有super方法也是一样,是调用父类的成员变量或者方法,那就加上这个关键字,不要省略.

建造者模式(Builder Pattern)也叫做生成器模式,其定义如下:

Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分 离,使得同样的构建过程可以创建不同的表示。)

 建造者模式的优点

 使用场景

● 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。

● 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。

● 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。

● 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程 中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有个金丝熊叫老许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值