天天看点

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

版权声明:尊重博主原创文章,转载请注明出处哦~http://blog.csdn.net/eson_15/article/details/51325765

        假如现在要生产两种车,奔驰和宝马,这两辆车都有共性,我们所需要关注的是单个车的运行过程,这才是老板所关心的点所在。我们先这样想,针对这个需求,我们要找到一个切入点,那就是产品类,每个车都是一个产品,那么在产品类中我们可以控制车的运行顺序,这样每个车都可以拥有自己想要的顺序了。基于此,我们设计如下类图:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

         我们看到carmodel中有个setsequence方法,通过传入一个arraylist来控制运行顺序,run方法根据这个arraylist中保存的顺序执行,然后奔驰车和宝马车分别继承这个carmodel即可,这貌似是很好的实现,它很像上一节的模板方法模式,只是多了个方法可以设置运行顺序。我们看一下carmodel具体代码的实现:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public abstract class carmodel {  

    private arraylist<string> sequence = new arraylist<string>(); //维护一个arraylist保存执行命令关键字  

    protected abstract void start();  

    protected abstract void stop();  

    protected abstract void alarm();  

    protected abstract void engineboom();  

    final public void run() {  

        for(int i = 0; i < this.sequence.size(); i ++) { //根据arraylist中保存的顺序执行相应的动作  

            string actionname = this.sequence.get(i);  

            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) { //获得执行顺序的命令,即一个arraylist  

        this.sequence = sequence;  

}  

        carmodel中的setsequence方法允许客户自己设置一个顺序,我们看看子类的实现:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public class benzmodel extends carmodel {  

    @override  

    protected void start() {  

        system.out.println("奔驰启动……");  

    protected void stop() {  

        system.out.println("奔驰停止……");  

    protected void alarm() {  

        system.out.println("奔驰鸣笛……");  

    protected void engineboom() {  

        system.out.println("奔驰轰鸣");  

//宝马就略了……一样的  

        下面我们增加一个测试类实现该需求:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public class client {  

    public static void main(string[] args) {  

        benzmodel benz = new benzmodel();  

        //存放run顺序  

        arraylist<string> sequence = new arraylist<string>();  

        sequence.add("engine boom"); //老板说:跑之前先轰鸣比较帅!  

        sequence.add("start");  

        sequence.add("stop");  

        //我们把这个顺序赋予奔驰  

        benz.setsequence(sequence);  

        benz.run();  

        这样好像已经顺利完成了任务了,但是别忘了,我们这只是满足了一个需求,如果下一个需求是宝马车只轰鸣,再下一个需求是奔驰车只跑不停……等等……那岂不是要一个个写测试类来实现?显然这不是我们想要的。

        我们可以这样做:为每种产品模型定义一个建造者,你要啥顺序直接告诉建造者,由建造者来建造即可,于是我们重新设计类图:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

        我们增加了一个carbuilder类,由它来组装各个车模型,要什么类型的顺序就由相关的子类去完成即可,我们来看看carbuilder的代码:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public abstract class carbuilder {  

    //建造一个模型,你要给我一个顺序要求  

    public abstract void setsequence(arraylist<string> sequence);  

    //设置完毕顺序后,就可以直接拿到这个车辆模型了  

    public abstract carmodel getcarmodel();  

        很简单,每个车辆模型都要有确定的运行顺序,然后才能返回一个车辆模型,奔驰车和宝马车组装者的代码如下:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public class benzbuilder extends carbuilder {  

    private benzmodel benz = new benzmodel(); //奔驰车模型  

    public void setsequence(arraylist<string> sequence) {  

        this.benz.setsequence(sequence); //设置奔驰车模型的运行顺序  

    public carmodel getcarmodel() {  

        return this.benz; //将这个模型返回  

//宝马车一样,不写了……  

        现在两辆车的组装者都写好了,现在我们写一个测试类来测试一下:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

        sequence.add("engine boom");  

        //要用这个顺序造一辆奔驰  

        benzbuilder benzbuilder = new benzbuilder();  

        //把顺序给奔驰组装者  

        benzbuilder.setsequence(sequence);  

        //奔驰组装者拿到顺序后就给你生产一辆来  

        benzmodel benz = (benzmodel) benzbuilder.getcarmodel();  

       如果我要生产一辆宝马车,只需要换成宝马车的组装者即可,这样我们不用直接访问产品类了,全部访问组装者就行,是不是感觉到很方便,我管你怎么生产,我扔给你个顺序,你给我弄辆车出来,要的就是这种效果!

        可是人的需求是个无底洞,特别是老板,他哪天不爽了,又要换顺序,这样还是挺麻烦的,四个过程(start、stop、alarm、engine boom)按排列组合也有很多中情况,我们不能保证老板想要哪种顺序,咋整?无奈,我们只能使出最后的杀手锏了,找个设计师过来指挥各个时间的先后顺序,然后为每种顺序指定一个代码,你说一种我们立刻就给你生产!我们再修改一下类图……

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

        类图看着有点复杂,其实不然,只是在原来的基础上增加了一个director类充当着设计师的角色,负责按照指定的顺序生产模型,比如我们要一个a顺序的奔驰车,b顺序的奔驰车,a顺序的宝马车,b顺序的宝马车……等等,我们来看下director类的代码:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

public class director {  

    private arraylist<string> sequence = new arraylist<string>();  

    private benzbuilder benzbuilder = new benzbuilder();  

    private bwmbuilder bwmbuilder = new bwmbuilder();  

    //a顺序的奔驰车  

    public benzmodel getabenzmodel() {  

        this.sequence.clear();  

        this.sequence.add("start");  

        this.sequence.add("stop");  

        //返回a顺序的奔驰车  

        this.benzbuilder.setsequence(sequence);  

        return (benzmodel) this.benzbuilder.getcarmodel();  

    //b顺序的奔驰车  

    public benzmodel getbbenzmodel() {  

        this.sequence.add("engine boom");  

        //返回b顺序的奔驰车  

    //c顺序的宝马车  

    public benzmodel getcbwmmodel() {  

        this.sequence.add("alarm");  

        //返回c顺序的宝马车  

        this.bwmbuilder.setsequence(sequence);  

        return (benzmodel) this.bwmbuilder.getcarmodel();  

    //d顺序的宝马车  

    public benzmodel getdbwmmodel() {  

        //返回d顺序的宝马车  

    //还有很多其他需求,设计师嘛,想啥需求就给你弄啥需求  

        有了这样一个设计师,我们的测试类就更容易处理了,比如现在老板要10000辆a类奔驰车,100000辆b类奔驰车,20000c类型宝马车,d类型不要:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

        director director = new director();  

        for(int i = 0; i < 10000; i ++) {  

            director.getabenzmodel();  

        for(int i = 0; i < 100000; i ++) {  

            director.getbbenzmodel();  

        for(int i = 0; i < 20000; i ++) {  

            director.getcbwmmodel();  

        是不是很清晰很简单,我们重构代码的最终第就是简单清晰。这就是建造者模式。

        我们来看看建造者模式的一般定义:separate the construction of a complex object from its representation so that the same construction process can create different representations. 即:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。比如上面的例子,我们可以用同样的顺序构造不同的车。建造者模式的通用类图如下:

【java设计模式】之 建造者(Builder)模式 1. 汽车无休止的改造 2. 建造者模式的定义 3. 建造者模式的优点 4. 建造者模式的使用场景

        product是最终的产品类,builder是建造者,director是指挥者。director负责安排已有模块的顺序,然后告诉builder开始建造。

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

        2)建造者独立,容易扩展:benzbuilder和bmwbuilder是相互独立的,对系统扩展非常有利。

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

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

        2)多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不想同时,可以使用建造者模式。

        3)产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这时候可以使用建造者模式。

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

        到这里,我们会发现,建造者模式和工厂方法模式有点像。但是两者有区别:建造者模式关注的是零件类型和装配工艺(顺序),而工厂模式是创建一个对象,这是最大不同的地方。

        创建者模式就介绍这么多吧,如有错误之处,欢迎留言指正~

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!