前言:关于传递参数,当参数过多的时候我们可以考虑使用建造者模式。

#没用 Builder模式 之前是这样传参的:

如下所示,构造方法里面的参数一大堆,看起来就非常的混乱。

  • 用了Builder模式之后是这样的

  新建一个静态内部类Buider,通过它来构建参数,然后返回一个新的对象,最后在新的对象内部把值赋给当前类的成员变量,如下图:

  • 可以看到改造后的代码,只存在一个Buider静态内部类,瞬间感觉清晰了不少。

  • 附加一个简单的demo:

  • class User {
    // 下面是“一堆”的属性
    private String name;
    private String password;
    private String nickName;
    private int age; // 构造方法私有化,不然客户端就会直接调用构造方法了
    private User(String name, String password, String nickName, int age) {
    this.name = name;
    this.password = password;
    this.nickName = nickName;
    this.age = age;
    }
    // 静态方法,用于生成一个 Builder,这个不一定要有,不过写这个方法是一个很好的习惯,
    // 有些代码要求别人写 new User.UserBuilder().a()...build() 看上去就没那么好
    public static UserBuilder builder() {
    return new UserBuilder();
    } public static class UserBuilder {
    // 下面是和 User 一模一样的一堆属性
    private String name;
    private String password;
    private String nickName;
    private int age; private UserBuilder() {
    } // 链式调用设置各个属性值,返回 this,即 UserBuilder
    public UserBuilder name(String name) {
    this.name = name;
    return this;
    } public UserBuilder password(String password) {
    this.password = password;
    return this;
    } public UserBuilder nickName(String nickName) {
    this.nickName = nickName;
    return this;
    } public UserBuilder age(int age) {
    this.age = age;
    return this;
    } // build() 方法负责将 UserBuilder 中设置好的属性“复制”到 User 中。
    // 当然,可以在 “复制” 之前做点检验
    public User build() {
    if (name == null || password == null) {
    throw new RuntimeException("用户名和密码必填");
    }
    if (age <= 0 || age >= 150) {
    throw new RuntimeException("年龄不合法");
    }
    // 还可以做赋予”默认值“的功能
    if (nickName == null) {
    nickName = name;
    }
    return new User(name, password, nickName, age);
    }
    }
    }
  • 核心是:先把所有的属性都设置给 Builder,然后 build() 方法的时候,将这些属性复制给实际产生的对象。
    
    看看客户端的调用:
    
    public class APP {
    public static void main(String[] args) {
    User d = User.builder()
    .name("foo")
    .password("pAss12345")
    .age(25)
    .build();
    }
    }
  • 2018年1月19日 10:20:12 更新


   附加一个swagger中看到的建造者模式:

/*
*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/ package springfox.documentation.builders; import com.fasterxml.classmate.ResolvedType;
import com.google.common.base.Optional;
import springfox.documentation.schema.ModelReference;
import springfox.documentation.service.AllowableValues;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.VendorExtension; import java.util.List; import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.builders.BuilderDefaults.*; public class ParameterBuilder {
private String name;
private String description;
private String defaultValue;
private boolean required;
private boolean allowMultiple;
private AllowableValues allowableValues;
private String paramType;
private String paramAccess;
private ResolvedType type;
private ModelReference modelRef;
private boolean hidden;
private List<VendorExtension> vendorExtensions = newArrayList(); /**
* Copy builder
*
* @param other parameter to copy from
* @return this
*/
ParameterBuilder from(Parameter other) {
return name(other.getName())
.allowableValues(other.getAllowableValues())
.allowMultiple(other.isAllowMultiple())
.defaultValue(other.getDefaultValue())
.description(other.getDescription())
.modelRef(other.getModelRef())
.parameterAccess(other.getParamAccess())
.parameterType(other.getParamType())
.required(other.isRequired())
.type(other.getType().orNull())
.hidden(other.isHidden())
.vendorExtensions(other.getVendorExtentions());
} /**
* Updates the parameter name
*
* @param name - name of the parameter
* @return this
*/
public ParameterBuilder name(String name) {
this.name = defaultIfAbsent(name, this.name);
return this;
} /**
* Updates the description of the parameter
*
* @param description - description
* @return this
*/
public ParameterBuilder description(String description) {
this.description = defaultIfAbsent(description, this.description);
return this;
} /**
* Updates the default value of the parametr
*
* @param defaultValue - default value
* @return this
*/
public ParameterBuilder defaultValue(String defaultValue) {
this.defaultValue = defaultIfAbsent(defaultValue, this.defaultValue);
return this;
} /**
* Updates if the parameter is required or optional
*
* @param required - flag to indicate if the parameter is required
* @return this
*/
public ParameterBuilder required(boolean required) {
this.required = required;
return this;
} /**
* Updates if the parameter should allow multiple values
*
* @param allowMultiple - flag to indicate if the parameter supports multi-value
* @return this
*/
public ParameterBuilder allowMultiple(boolean allowMultiple) {
this.allowMultiple = allowMultiple;
return this;
} /**
* Updates if the parameter is bound by a range of values or a range of numerical values
*
* @param allowableValues - allowable values (instance of @see springfox.documentation.service.AllowableListValues
* or @see springfox.documentation.service.AllowableRangeValues)
* @return
*/
public ParameterBuilder allowableValues(AllowableValues allowableValues) {
this.allowableValues = emptyToNull(allowableValues, this.allowableValues);
return this;
} /**
* Updates the type of parameter
*
* @param paramType - Could be header, cookie, body, query etc.
* @return this
*/
public ParameterBuilder parameterType(String paramType) {
this.paramType = defaultIfAbsent(paramType, this.paramType);
return this;
} /**
* Updates the parameter access
*
* @param paramAccess - parameter access
* @return this
*/
public ParameterBuilder parameterAccess(String paramAccess) {
this.paramAccess = defaultIfAbsent(paramAccess, this.paramAccess);
return this;
} /**
* Updates the type of parameter
*
* @param type - represents the resolved type of the parameter
* @return this
*/
public ParameterBuilder type(ResolvedType type) {
this.type = defaultIfAbsent(type, this.type);
return this;
} /**
* Represents the convenience method to infer the model reference
* Consolidate or figure out whats can be rolled into the other.
*
* @param modelRef
* @return
*/
public ParameterBuilder modelRef(ModelReference modelRef) {
this.modelRef = defaultIfAbsent(modelRef, this.modelRef);
return this;
} /**
* Updates if the parameter is hidden
*
* @param hidden - flag to indicate if the parameter is hidden
* @return this
*/
public ParameterBuilder hidden(boolean hidden) {
this.hidden = hidden;
return this;
} /**
* Updates the parameter extensions
*
* @param extensions - parameter extensions
* @return this
*/
public ParameterBuilder vendorExtensions(List<VendorExtension> extensions) {
this.vendorExtensions.addAll(nullToEmptyList(extensions));
return this;
} public Parameter build() {
return new Parameter(
name,
description,
defaultValue,
required,
allowMultiple,
modelRef,
Optional.fromNullable(type),
allowableValues,
paramType,
paramAccess,
hidden,
vendorExtensions);
}
}

总结:

相比只通过一个构造器创建实例,JavaBean模式的实例的构造过程被分成了好几个过程。

我们完全有可能在属性不完整的情况下使用这个实例。

当然,Builder也有缺点。

缺点1.创建实例前都要创建一个Builder实例。

缺点2.Builder模式编写起来较为冗长。

但是,当构建一个实例需要很多步骤(或者很多让人混淆的参数)的时候,Builder模式是个不错的选择。

    

【原】使用Builder模式替代构造参数传参的更多相关文章

  1. python笔记之强制函数以关键字参数传参

    最近学习python,学到了函数传参,看到了以下这个特殊情况,特此来做个笔记 def add(*, x, y): print(x, y) 以上函数定义后,该怎么传参?前面的那个*号是做什么用的? 我们 ...

  2. Vue系列之 => 使用钩子函数的第二个参数传参

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Hibernate的HQL语句中定位参数和具名参数传参

    HQL查询: 1.有关hql查询语句中的问号参数形式,如果出现有多个问号,这对后面设置参数就比较麻烦. 如:from User user where user.name=? and user.age= ...

  4. 02.当构造参数过多时使用builder模式

    前言 <Effective Java>中文第三版,是一本关于Java基础的书,这本书不止一次有人推荐我看.其中包括我很喜欢的博客园博主五月的仓颉,他曾在自己的博文<给Java程序猿们 ...

  5. 解析《Effective Java》之多个构造器、Javabeans模式和Builder模式

    最近看<Effective Java>这本被很多同行称为神作的书,但是这本书很多地方缺少了举例不好懂,下面是关于我对书上知识的理解. 一.<Effective Java>中文版 ...

  6. Builder模式在Java中的应用

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  7. Builder模式(建造者模式)

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  8. Builder模式在Java中的应用(转)

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  9. Builder模式详解及其在Android开发中的应用

    一.引言 在Android开发中,采用Builder模式的代码随处可见,比如说Android系统对话框AlertDialog的使用或者是Android中的通知栏(Notification)的使用,又比 ...

随机推荐

  1. 红帽子系统链接加vm15秘钥一份

    vm15秘钥:YZ718-4REEQ-08DHQ-JNYQC-ZQRD0 红帽子系统下载链接:http://www.ddooo.com/softdown/60964.htm

  2. OpenvSwitch 解读

    OpenvSwitch 解读 报文匹配流程参考下图 调用流程(内核): ovs_vport_receive->ovs_dp_process_received_packet->ovs_flo ...

  3. Android------------fragment数据传递

    一.activity向fragment的数值之间的传递 关键点:fragment.setArguments(bundle);---->activity发出的信息      Bundle bund ...

  4. js判断图片是否加载完毕

    附件: https://www.jb51.net/article/102385.htm 问题:  .offset().top和$(window).scrollTop()每次刷新页面后滚动的值有时候会不 ...

  5. jzoj5923

    我們可以記f[i]表示i個點的連通圖的個數 則我們可以考慮將i個點不必聯通的圖個數(記為g)減去i個點的不連通圖個數 那麼f[i]=g[i]-c(j-1,i-1)f[j]gi-j 枚舉一個j,強制將j ...

  6. 栈的实现——c++

    栈(stack),是一种线性存储结构,它有以下几个特点: (01) 栈中数据是按照"后进先出(LIFO, Last In First Out)"方式进出栈的. (02) 向栈中添加 ...

  7. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  8. poj2479 Maximum sum

    http://poj.org/problem?id=2479 题目大意:给定一组n个整数:a ={a1, a2,…,我们定义一个函数d(a)如下: 你的任务是计算d(A).输入由T(<=30)测 ...

  9. getopt() getopt_long()函数手册[中文翻译]

    getopt()函数 getopt_long函数 函数原型(function prototype) #include <unistd.h> int getopt(int argc, cha ...

  10. JSTL介绍及使用

    JSTL介绍及使用 一.JSTL(JSP Standard Tag Library)简介 > JSTL是JSP的标准标签库 > JSTL为我们提供了一些常用的标签,供我们日常开发使用(if ...