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

#没用 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. PHP7 - 如何禁用Xdebug

    操作系统:Cent OS 7 什么是Xdebug?看它的官方网站介绍: https://xdebug.org/index.php 为什么要禁用呢?这是因为Composer,这两种工具有冲突,在使用Co ...

  2. laravel 的passport Oauth 认证登录请求 的 oauth_token 重置

    laravel 的passport Oauth 认证登录请求 的 oauth_token 重置    使用API登录认证是需要获取访问令牌,方法为: 参数: grant_type —— 密码模式固定为 ...

  3. 算法(Algorithm)

    算法就是"把解决问题的步骤无一遗漏地用文字或图表示出来". 在解决问题的步骤中,有了与直觉相关的因素,就不是算法了.既然不是算法,也就不能用程序表示了.

  4. docker私服registry管理镜像

    前言 首先试想这样一个场景:当在自己的机器上(docker中)构建了mysql镜像,eureka镜像等等微服务镜像,这些镜像有可能需要放到其他的机器上docker环境中去运行,实行分布式架构部署.但如 ...

  5. linux中进程和计划任务管理

    进程和计划任务管理 1. 程序和进程的关系 程序:保存在硬盘.光盘等介质中的可执行代码和数据:静态保存的代码 进程:在 CPU 及内存中运行的程序代码:动态执行的代码:父.子进程:每个进程可以创建一个 ...

  6. 解决后台json数据返回的字段需要替换的问题

    有时候后台json数据返回的字段含有“id”,也有可能是有时候为了减少代码的冗余,两页面之间只是数据模型个别属性的区别,所以这时候最好是用到模型属性的替换,用新的属性替换返回的json数据的字段.这里 ...

  7. POJ 1243

    #include <iostream> #include <algorithm> #include <cmath> #define MAXN 50 using na ...

  8. C++ 实现Biginteger

    网上C++版Biginteger参差不齐,一下子没有找到一个令人满意Biginteger,最近用c++改写了一下C#版 BigInteger,可以用于RSA大素数的生成,分享给大家.也请大家批评指正改 ...

  9. openssl生成RSA格式的公私钥,并转为pkcs8格式

    第一步:生成私钥,这里我们指定私钥的长度为2048 openssl genrsa -out rsa_private_key.pem 2048 第二步:根据私钥生成对应的公钥: openssl rsa ...

  10. [转]MVC HtmlHelper用法大全

    原文链接:http://www.cnblogs.com/jyan/archive/2012/07/23/2604474.html HtmlHelper用来在视图中呈现 HTML 控件. 以下列表显示了 ...