设计模式5-建造者模式

      在上一篇中简单的说了下模板方法模式,这篇将简单的介绍下建造者模式,基于前面的http://blog.csdn.net/j903829182/article/details/76576712

模式的一个改造。比如汽车启动的顺序需要可以控制设置,上篇的模式就不能够满足要求了,这里使用建造者模式来解决可以手动控制启动顺序的需求。类图如下:




    编写一个汽车模型的抽象类,代码如下:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 * 建造者模式
 */
public abstract class CarModel {
    //这个参数是各个基本方法执行的顺序
    private ArrayList<String> sequence = new ArrayList<>();
    /**
     * 模型启动准备开始跑了
     */
    abstract void start();

    /**
     * 能发动还要能停下来
     */
    abstract void stop();

    /**
     * 喇叭会响,可以出什么声音根据车子来决定
     */
    abstract void alarm();

    /**
     * 引擎会响
     */
    abstract void engineBoom();

    /**
     * 车子会跑
     */
    public void run(){
        for (int i= 0;i< this.sequence.size();i++) {
            String actionName = this.sequence.get(i);
            if ("start".equals(actionName)){
                this.start();//启动汽车
            }else if ("stop".equals(actionName)){
                this.stop();//停止汽车
            }else if ("alarm".equals(actionName)){
                this.alarm();//喇叭开始响了
            } else if ("enginboom".equals(actionName)) {
                this.engineBoom();//引擎开始响了
            }
        }
    }

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


     使用上面的汽车模型,生产出宝马模型,代码如下:

package com.jack.buildermodel;

/**
 * Created by jack on 2017/8/3.
 * 宝马模型
 */
public class BMWModel extends CarModel {
    @Override
    void start() {
        System.out.println("宝马跑起来");
    }

    @Override
    void stop() {
        System.out.println("宝马停车");
    }

    @Override
    void alarm() {
        System.out.println("宝马按喇叭");
    }

    @Override
    void engineBoom() {
        System.out.println("宝马引擎响起来");
    }
}


   再使用汽车模型,生产出奔驰模型,代码模型如下:

package com.jack.buildermodel;

/**
 * Created by jack on 2017/8/3.
 * 奔驰模型
 */
public class BenzModel extends CarModel {
    @Override
    void start() {
        System.out.println("奔驰跑起来");
    }

    @Override
    void stop() {
        System.out.println("奔驰停车");
    }

    @Override
    void alarm() {
        System.out.println("奔驰按喇叭");
    }

    @Override
    void engineBoom() {
        System.out.println("奔驰引擎响起来");
    }
}


     到这里,宝马奔驰的模型都有了,下面我们来开始生产汽车,指定顺序让汽车跑起来吧!代码如下:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 */
public class MainTest1 {
    public static void main(String[] args) {
        CarModel carModel = new BenzModel();
        //存放汽车的顺序动作
        ArrayList<String> sequence = new ArrayList();
        sequence.add("enginboom");
        sequence.add("start");
        sequence.add("stop");
        sequence.add("enginboom");
        //把动作赋予奔驰
        carModel.setSequence(sequence);
        carModel.run();
    }
}


    运行上面的代码,输出如下:

奔驰引擎响起来
奔驰跑起来
奔驰停车
奔驰引擎响起来

     现在又有这样的需要,我需要一个宝马模型只要启动,停止,其他什么也不要,一个只要喇叭,然后启动,然后停止,第四个。。。。我们不可能为每个场景写一个类来满足,者时候我们给产品模型定义一个建造者,你要啥顺序直接告诉建造者,由建造者来建造,者就是建造者模型,类图如下:



     抽象汽车建造者:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 * 抽象类,建造者
 */
public abstract class CarBuilder {
    //建造一个模型,你需要给我一个顺序要求,就是车的动作
    public abstract void setSequence(ArrayList<String> sequence);
    //设置完毕顺序后,就可以直接拿到这个模型了
    public abstract CarModel getCarModel();
}


宝马建造者:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 * 宝马建造者
 */
public class BMWBuilder extends CarBuilder{
    private BMWModel bmwModel = new BMWModel();
    @Override
    public void setSequence(ArrayList<String> sequence) {
        this.bmwModel.setSequence(sequence);
    }

    @Override
    public CarModel getCarModel() {
        return this.bmwModel;
    }
}


奔驰建造者:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 * 奔驰建造者
 */
public class BenzBuilder extends CarBuilder{
    private BenzModel benzModel = new BenzModel();
    @Override
    public void setSequence(ArrayList<String> sequence) {
        this.benzModel.setSequence(sequence);
    }

    @Override
    public CarModel getCarModel() {
        return benzModel;
    }
}



   测试代码如下:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 */
public class MainTest2 {
    public static void main(String[] args) {
        ArrayList<String> sequence = new ArrayList();
        sequence.add("enginboom");
        sequence.add("start");
        sequence.add("stop");
        sequence.add("enginboom");
        //要一个奔驰
        BenzBuilder benzBuilder = new BenzBuilder();
        //设置顺序
        benzBuilder.setSequence(sequence);
        //制造一个奔驰出来
        CarModel benz = benzBuilder.getCarModel();
        benz.run();

        System.out.println("--------------------");

        //要一个通用顺序的宝马
        BMWBuilder bmwBuilder = new BMWBuilder();
        bmwBuilder.setSequence(sequence);
        CarModel bmw = bmwBuilder.getCarModel();
        bmw.run();
    }
}

奔驰引擎响起来
奔驰跑起来
奔驰停车
奔驰引擎响起来
--------------------
宝马引擎响起来
宝马跑起来
宝马停车
宝马引擎响起来

   上面是测试程序的输出。

   需求总是再变,我们不知道需要具体什么方式的启动顺序,那么我们可以把封装一个模型,把各个事件的先后顺序都指定一个代码,你说一种立刻就可以给出处理的方法,类图如下:




     上面的类图增加了一个Director类,还是比较简单的,负责按照指定顺序生产汽车模型,代码如下:

package com.jack.buildermodel;

import java.util.ArrayList;

/**
 * Created by jack on 2017/8/3.
 */
public class Director {
    private ArrayList<String> sequence = new ArrayList<>();
    //宝马建造者
    private BMWBuilder bmwBuilder = new BMWBuilder();
    //奔驰建造者
    private BenzBuilder benzBuilder = new BenzBuilder();

    /**
     * A类型车的奔驰模型,先start然后stop,其他没有
     * @return
     */
    public CarModel getABenzModel(){
        this.sequence.clear();
        this.sequence.add("start");
        this.sequence.add("stop");
        //按顺序返回一个奔驰车
        benzBuilder.setSequence(sequence);
        return benzBuilder.getCarModel();
    }

    /**
     * B类型车的奔驰模型,先发动引擎,然后start,stop,其他没有
     * @return
     */
    public CarModel getBBenzModel(){
        this.sequence.clear();
        this.sequence.add("enginboom");
        this.sequence.add("start");
        this.sequence.add("stop");
        //按顺序返回一个奔驰车
        this.benzBuilder.setSequence(sequence);
        return this.benzBuilder.getCarModel();
    }
    /**
     * C类型车的宝马模型,先按喇叭,然后start,stop,其他没有
     * @return
     */
    public CarModel getCBWMModel(){
        this.sequence.clear();
        this.sequence.add("alarm");
        this.sequence.add("start");
        this.sequence.add("stop");
        //按顺序返回一个奔驰车
        this.bmwBuilder.setSequence(sequence);
        return this.bmwBuilder.getCarModel();
    }

    /**
     * D类型车的宝马模型,就一个功能,就是跑
     * @return
     */
    public CarModel getDBWMModel(){
        this.sequence.clear();
        this.sequence.add("start");
        //按顺序返回一个奔驰车
        this.bmwBuilder.setSequence(sequence);
        return this.bmwBuilder.getCarModel();
    }
    //还可以有很多车型

}



    测试类代码如下:

package com.jack.buildermodel;

/**
 * Created by jack on 2017/8/3.
 */
public class MainTest3 {
    public static void main(String[] args) {
        Director director = new Director();
        //100辆A类型的车
        for (int i= 0 ;i<100;i++){
            director.getABenzModel();
        }
        //100辆B类型的车
        for (int i= 0 ;i<100;i++){
            director.getBBenzModel();
        }
        //100辆C类型的车
        for (int i= 0 ;i<100;i++){
            director.getCBWMModel();
        }
    }
}

  通用建造者模型类图如下:



   Product类:通常是实现了模板方法模式,如上面的BenzModel和BMWModel

   Builder抽象构建者:规范产品的组建,一般是由子类实现

   ConcreteBuilder具体构构建者:实现抽象类定义的所有方法,并返回一个组建好的对象。

   Director导演类:负责安排已经有的模块的顺序,然后告诉Builder开始构建


    建造者模式的优点:

封装性:使用建造者模式可以使客户端不必知道产品内部组成的细节

建造者独立,容易扩展

便于控制细节风险:由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他模块产生任何影响。


   建造者模式的使用场景:

1,相同的方法,不同的执行顺序,产生不同的世界结果时,可以采用建造者模式

2,多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时

3,产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能

4,再对象创建过程中使用到了系统中的一些其他对象,这些对象再产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。


 建造者模式关注的时零件类型和装配工艺顺序。

 代码在github里面,地址:https://github.com/wj903829182/springboot/tree/master/designpattern


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值