第2.1章 设计模式之Builder模式

本文详细介绍了Builder模式的应用场景和实现方式,特别是在参数众多时的优势。通过一个具体的JavaBean构造实例,展示了如何利用Builder模式简化对象创建过程。

如果使用过mybatis generator的人,你就知道了,这个插件自动生成example,就采用的是Builder模式来构建查询条件。
Joshua Bloch著的《Effective Java》中指示:遇到多个构造器参数时需要考虑构建器
传统的方式是通过构造函数重载的方式,那么什么时候会出现问题呢?构造函数如果有5个参数还可以容忍,如果有10个参数,怎么办呢?不停的重载?
构造函数重载
怎么解决这个问题,让它容易扩展呢?这里就采用了Builder模式.
看下面实例VmParams 这个JAVABean有很多属性,但是我们给他定义个private构造函数,也就是说VmParams我们不让它直接实例。那么谁来做呢?

  1. 找到build()方法,它返回的是VmParams对象,也就是说这个VmParams的构造交给了buid()
  2. 找到private VmParams构造函数,可以看到参数是builder。而VmParams的属性基本都是由builder赋值的,可以想象这些属性的set值在builder对象中肯定有一份。
  3. 果不其然,我们看静态内部类Builder,有相同的属性。
/**
 * 模板参数
 * 
 * @author dzm
 */
public class VmParams {
    /**
     * 包名路径
     */
    private final String packagePath;

    /**
     * 模块路径
     */
    private final String modulePath;

    /**
     * js路径
     */
    private final String jsPath;

    /**
     * jsp路径
     */
    private final String jspPath;

    private Bean bean;

    private final Annotation annotation;

    /**
     * 数据库连接配置
     */
    private final JDBCConnectionConfiguration jdbcConfig;

    /**
     * 产生代码bean的列表
     */
    private final List<String> beanNameList;

    /**
     * 子表清单
     */
    private final List<String> subBeanNameList;
    /**
     * 子表类清单
     */
    private List<ClassBean>  subClassBeanList;

    /**
     * 订单头
     */
    private final String mainBean;

    /**
     * 左表
     */
    private final String left;

    /**
     * 右表
     */
    private final String right;

    /**
     * 额外的参数
     */
    private final Map<String, Object> extras;

    private VmParams(Builder builder) {
        //
        this.annotation = builder.annotation;
        this.packagePath = builder.packagePath;
        this.modulePath = builder.modulePath;
        this.jsPath = builder.jsPath;
        this.jspPath = builder.jspPath;
        this.jdbcConfig = builder.jdbcConfig;
        this.beanNameList = builder.beanNameList;
        this.subBeanNameList = builder.subBeanNameList;
        this.mainBean = builder.mainBean;
        this.left = builder.left;
        this.right = builder.right;
        this.extras = builder.extras;
        _subBean2Class(subBeanNameList);
    }
    
    private void _subBean2Class(List<String> subBeanNameList){
        if (!CheckEmptyUtil.isEmpty(subBeanNameList)){
            this.subClassBeanList = new ArrayList<ClassBean>();
            for (String subBeanName:this.subBeanNameList){
                ClassBean classBean = new ClassBean();
                classBean.setClassPath(subBeanName);
                classBean.setBigName(StringUtil.getLastChar(subBeanName));
                classBean.setLittleName(StringUtil.toLowerCaseFirstOne(classBean.getBigName()));
                this.subClassBeanList .add(classBean);
            }
        }
    }

    /**
     * 将参数交给构建器
     * 
     * @author dzm
     */
    public static class Builder {
        private Annotation annotation;

        private String packagePath;

        private String modulePath;

        private String jsPath;

        private String jspPath;

        private JDBCConnectionConfiguration jdbcConfig;

        private List<String> beanNameList;

        private List<String> subBeanNameList;

        private String mainBean;

        private String left;

        private String right;

        private Map<String, Object> extras;

        public Builder() {

        }
        
        /**
         * 添加额外的参数
         * @param key
         * @param value
         * @return
         */
        public Builder addExtra(String key, Object value) {
            if (null == extras) {
                extras = new HashMap<String, Object>();
            } 
            extras.put(key, value);
            return this;
        }

        /**
         * 添加subbean
         * 
         * @param subBeanName
         * @return
         */
        public Builder addSubBeanName(String subBeanName) {
            if (null == subBeanNameList) {
                subBeanNameList = new ArrayList<String>();
            }
            subBeanNameList.add(subBeanName);
            return this;
        }

        /**
         * 添加bean
         * 
         * @return
         */
        public Builder addBeanName(String beanName) {
            if (null == beanNameList) {
                beanNameList = new ArrayList<String>();
            }
            beanNameList.add(beanName);
            return this;
        }

        public Builder setAnnotation(Annotation annotation) {
            this.annotation = annotation;
            return this;
        }

        public Builder setPackagePath(String packagePath) {
            this.packagePath = packagePath;
            return this;
        }

        public Builder setModulePath(String modulePath) {
            this.modulePath = modulePath;
            return this;
        }

        public Builder setJsPath(String jsPath) {
            this.jsPath = jsPath;
            return this;
        }

        public Builder setJspPath(String jspPath) {
            this.jspPath = jspPath;
            return this;
        }

        public Builder setJdbcConfig(JDBCConnectionConfiguration jdbcConfig) {
            this.jdbcConfig = jdbcConfig;
            return this;
        }

        public Builder setMainBean(String mainBean) {
            this.mainBean = mainBean;
            return this;
        }

        public Builder setLeft(String left) {
            this.left = left;
            return this;
        }

        public Builder setRight(String right) {
            this.right = right;
            return this;
        }

        /**
         * 构建参数
         * 
         * @return
         */
        public VmParams build() {
            return new VmParams(this);
        }
    }

    public Bean getBean() {
        return bean;
    }

    public void setBean(Bean bean) {
        this.bean = bean;
    }

    public Annotation getAnnotation() {
        return annotation;
    }

    public String getPackagePath() {
        return packagePath;
    }

    public String getModulePath() {
        return modulePath;
    }

    public String getJsPath() {
        return jsPath;
    }

    public String getJspPath() {
        return jspPath;
    }

    public JDBCConnectionConfiguration getJdbcConfig() {
        return jdbcConfig;
    }

    public List<String> getBeanNameList() {
        return beanNameList;
    }

    public List<String> getSubBeanNameList() {
        return subBeanNameList;
    }

    public String getMainBean() {
        return mainBean;
    }

    public String getLeft() {
        return left;
    }

    public String getRight() {
        return right;
    }

    public Map<String, Object> getExtras() {
        return extras;
    }

    public List<ClassBean> getSubClassBeanList() {
        return subClassBeanList;
    }

    public void setSubClassBeanList(List<ClassBean> subClassBeanList) {
        this.subClassBeanList = subClassBeanList;
    }

}

为什么认为Builder模式对参数构建有很大优势呢,我们看看他怎么调用的.
参数构建都是Builder一直那么"."下去,如果增加参数,那么增加一个set就可以了,
是不是很方便。

 VmParams vmParams = new VmParams.Builder()
       .setJsPath(jsPath).setJspPath(jspPath).setModulePath(modulePath).setPackagePath(packagePath)
            .setJdbcConfig(getJdbcConfig())
            .addBeanName(SmsEmployee.class.getName())
            .addBeanName(SmsEmployeeSchedule.class.getName())
            .build();

虽然Builder模式构建对象优势很明显,开销姑且不论,对构造对象变得冗长。
因此它在有很多参数或者你认为将来可能会有很多参数的时候使用。
如果有人看过温昱的《一线架构师实践指南》,
质量属性关系矩阵
可扩展性与性能是冲突的,增加了可扩展性,那么势必就会牺牲性能。
在某性能十分注重性能地方,Builder模式可能有问题,但是一般做应用系统或者非大数据的系统,基本都合适。估计什么是十分注重性能,这个很难定义。所以尽可大胆使用。
如果你看过极光推送的sdk代码,他们用的里面也有Builder模式。有兴趣可以看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

warrah

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

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

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

打赏作者

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

抵扣说明:

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

余额充值