建造者模式

来源:互联网 发布:小程序服务器域名要求 编辑:程序博客网 时间:2024/05/22 03:53

定义

        将复杂对象的构建与它的表示分离,使得相同的构建过程可以创建不同的表示。
        在创建对象时,由Director决定Builder方法调用顺序(即装配过程、构建过程),由builder负责生产各个对象(即创建过程)。
        当修改传入到Director的Builder不同时,即使是相同的构建过程,由于Builder各个方法的返回值不同,最终得到的也是不同的产品。这就是“相同的构建过程可以创建不同的表示”。

关键词

        精细控制——对各个部件分别控制,产品的创建过程更加精细,也强调了产品构建的过程。如Dialog涉及到部分比较多,因此需要分别控制,才能显现出不同的dialog。
        分离构建与表示——构建与表示分离,能更方便地拥抱两者的变化,也可以方便构建与表示的重复使用。如果省略Director,则Builder模式没有该作用。

成员

        抽象建造者:建造者的父类,为产品的各个部件定义一个工厂方法。一般来说,各个工厂方法是空实现,这样方便了子类根据需要重写自己感兴趣的方法。
        指挥者(Director)主要作用就是定义装配过程,按一定顺序调用建造者中各个工厂方法(即装配过程),它控制着建造者一步步的构建产品,并在最终返回一个完整的产品。

示例

//指导者public class ProductDirector {    public Product getProduct(Builder builder) {        builder.build();//由指导者一步步地指导建造者创建Product对象        builder.buildList();        builder.buildName();        builder.buildScore();        return builder.getProduct();    }}
一个具体的Builder如下:
//定义创建各个部件的方法public abstract class Builder {    protected abstract void build();    protected abstract void buildScore();    protected abstract void buildName();    protected abstract void buildList();    public abstract Product getProduct();}//实现各个工厂方法,并在最后一步将组装完毕的产品返回public class ProductBuilder extends Builder {    private Product product;    @Override    protected void build() {        product = new Product();    }    @Override    protected void buildScore() {        int[] score = {90, 100, 85};        product.setScore(score);    }    @Override    protected void buildName() {        product.setName("张三");    }    @Override    protected void buildList() {        ArrayList<String> list = new ArrayList<>(3);        list.add("语文");        list.add("诗词");        list.add("数学");        product.setList(list);    }    @Override    public Product getProduct() {        return product;    }}

省略Director

        有些时候可以将Director省略,而在Builder类中添加多个方法代替。每一个方法按照一定的顺序调用各个部件的工厂方法,并最终组装成各个不同的产品——将Director的作用降低成方法,并定义在Builder中。但,当顺序太多时,建议使用Director。
        另外,如果装配过程不影响最终的产品(出可以说没有装配过程),可以省略Director。如应用中的例子。
        结合链接编程更方便——参考Dialog使用Builder模式。

应用

        手机端在发起网络请求时,不同的接口需要配置的数据不同,比如http请求头、url、请求参数、超时时间、加密级别等。解决这个问题的思路有二:
第一种:
        定义多个重载方法,每一个重载方法需要传递不同的参数,以满足不同接口对不同配置的需求。
第二种:
        将所有的请求封装成一个类,通过建造者创建该类。在使用时,通过调用建造者中不同的配置方法,为请求进行配置,当配置完成的时候通过建造者中的build()方法生成一个请求对象。
        通过建造者创建时,可以使用链式编程。看起来更简明。

比较

        在抽象工厂模式中,工厂只提供了一个一下子获取完整对象的方法,而无法对对象本身的一些组件进行控制(虽然可以通过请求参数的形式改变一个对象的某些组件,但如果参数过多且非必需,就会导致方法参数的臃肿以及使用的不方便——如果定义一堆的重载方法也不够灵活)。
        建造者却会为每一个组件提供一个工厂方法,由子类选择性完成各个组件的指定,并最终装配成一个完整的产品。因此,当产品比较复杂、组件较多时,使用建造者模式代替多参数的工厂方法是一个很好的选择。
        1,由于对各个部件提供了工厂方法,所以更利于对产品的精细控制,以及对各个部件构建方法的复用。虽然使用工厂方法在创建对象时,也能对各个部件进行定制,但这种定制并没有办法进行复用。
        2,抽象工厂提供了创建多个对象的方法,而建造者只是创建一个对象,只不过可以对该对象进行精细定制。
        3,装配过程和构建过程分开,使得同样的装配过程得到不同的对象(各部件不同,只需要修改传入Director中的Builder即可)。而工厂方法很难做到这点。

总结

        1,有多个维度变化时,将多个维度拆分成相互独立的部分,并通过组合的方式协同工作,这更利于变化的发生以及重复利用。

原创粉丝点击