【原】使用Builder模式替代构造参数传参
前言:关于传递参数,当参数过多的时候我们可以考虑使用建造者模式。
#没用 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);
- }
- }
- }
- class User {
- 核心是:先把所有的属性都设置给 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模式替代构造参数传参的更多相关文章
- python笔记之强制函数以关键字参数传参
最近学习python,学到了函数传参,看到了以下这个特殊情况,特此来做个笔记 def add(*, x, y): print(x, y) 以上函数定义后,该怎么传参?前面的那个*号是做什么用的? 我们 ...
- Vue系列之 => 使用钩子函数的第二个参数传参
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Hibernate的HQL语句中定位参数和具名参数传参
HQL查询: 1.有关hql查询语句中的问号参数形式,如果出现有多个问号,这对后面设置参数就比较麻烦. 如:from User user where user.name=? and user.age= ...
- 02.当构造参数过多时使用builder模式
前言 <Effective Java>中文第三版,是一本关于Java基础的书,这本书不止一次有人推荐我看.其中包括我很喜欢的博客园博主五月的仓颉,他曾在自己的博文<给Java程序猿们 ...
- 解析《Effective Java》之多个构造器、Javabeans模式和Builder模式
最近看<Effective Java>这本被很多同行称为神作的书,但是这本书很多地方缺少了举例不好懂,下面是关于我对书上知识的理解. 一.<Effective Java>中文版 ...
- Builder模式在Java中的应用
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- Builder模式(建造者模式)
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- Builder模式在Java中的应用(转)
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- Builder模式详解及其在Android开发中的应用
一.引言 在Android开发中,采用Builder模式的代码随处可见,比如说Android系统对话框AlertDialog的使用或者是Android中的通知栏(Notification)的使用,又比 ...
随机推荐
- 网易云首席安全架构师谈安全新形势:DDOS两三天,游戏玩家数从几万降到几百
本文由 网易云发布. 安全是一个永恒的话题,在业务不断云化.攻击越来越复杂的当下,互联网安全呈现了出什么样的严峻形势?对这些形势,网易云又是如何应对的? 网易云首席安全架构师沈明星 4月13日,网易 ...
- TensorFlow从1到2(十)带注意力机制的神经网络机器翻译
基本概念 机器翻译和语音识别是最早开展的两项人工智能研究.今天也取得了最显著的商业成果. 早先的机器翻译实际脱胎于电子词典,能力更擅长于词或者短语的翻译.那时候的翻译通常会将一句话打断为一系列的片段, ...
- 修改tomcat7编码问题(重定向等)
修改tomcat默认编码格式: 修改tomcat下的conf/server.xml文件,找到如下代码: <Connector port="8080" protocol=&qu ...
- docker registry 私有仓库 安装配置、查询、删除
#++++++++++++++++++++++++++++++ #docker-registry 私有仓库 #搜索,下载register镜像 docker search registry docker ...
- Qt5学习笔记(基础)
按钮 #include <QApplication> /*应用程序抽象类*/ #include <QWidget> //窗口类 #include <QPushButton ...
- LINUX中如何查看某个端口是否被占用
之前查询端口是否被占用一直搞不明白,问了好多人,终于搞懂了,现在总结下: 1.netstat -anp |grep 端口号 如下,我以3306为例,netstat -anp |grep ...
- 《JAVA与模式》之桥梁模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述桥梁(Bridge)模式的: 桥梁模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式. ...
- js的let语句在安卓手机端的QQ浏览器出错的问题
关于JavaScript里面的let,let 语句可以声明一个块级作用域的本地变量,并且可选的将其初始化为一个值. <ul id="list"> </ul> ...
- (转)mysql原生在线ddl和pt-osc原理解析
原文:http://blog.csdn.net/zengxuewen2045/article/details/52017247 https://github.com/mysql-inception/i ...
- Mime、base64编码
第一部分 在阮一峰老师的博客中,是这样介绍Mime的: MIME的全称是"Multipurpose Internet Mail Extensions",中译为"多用途互联 ...