如何改进构建器模式?

2024-04-14

动机

最近我寻找一种方法来初始化复杂的对象,而不需要向构造函数传递大量参数。我尝试使用构建器模式,但我不喜欢这样的事实,即我无法在编译时检查是否确实设置了所有需要的值。

传统建造者模式

当我使用构建器模式来创建我的Complex对象,创建更加“类型安全”,因为更容易看出参数的用途:

new ComplexBuilder()
        .setFirst( "first" )
        .setSecond( "second" )
        .setThird( "third" )
        ...
        .build();

但现在我遇到了一个问题,我很容易错过一个重要的参数。我可以在里面检查一下build()方法,但这只是在运行时。在编译时,如果我错过了什么,没有任何东西会警告我。

增强的构建器模式

现在我的想法是创建一个构建器,如果我错过了所需的参数,它会“提醒”我。我的第一次尝试如下所示:

public class Complex {
    private String m_first;
    private String m_second;
    private String m_third;

    private Complex() {}

    public static class ComplexBuilder {
        private Complex m_complex;

        public ComplexBuilder() {
            m_complex = new Complex();
        }

        public Builder2 setFirst( String first ) {
            m_complex.m_first = first;
            return new Builder2();
        }

        public class Builder2 {
            private Builder2() {}
            Builder3 setSecond( String second ) {
                m_complex.m_second = second;
                return new Builder3();
            }
        }

        public class Builder3 {
            private Builder3() {}
            Builder4 setThird( String third ) {
                m_complex.m_third = third;
                return new Builder4();
            }
        }

        public class Builder4 {
            private Builder4() {}
            Complex build() {
                return m_complex;
            }
        }
    }
}

正如您所看到的,构建器类的每个设置器都会返回不同的内部构建器类。每个内部构建器类只提供一个 setter 方法,最后一个仅提供 build() 方法。

现在对象的构造再次如下所示:

new ComplexBuilder()
    .setFirst( "first" )
    .setSecond( "second" )
    .setThird( "third" )
    .build();

...但是没有办法忘记所需的参数。编译器不会接受它。

可选参数

如果我有可选参数,我会使用最后一个内部构建器类Builder4像“传统”构建器一样设置它们,返回自身。

问题

  • 这是众所周知的模式吗?它有一个特殊的名字吗?
  • 你看到任何陷阱吗?
  • 您是否有任何改进实施的想法 - 从减少代码行的意义上来说?

传统的构建器模式已经处理了这个问题:只需在构造函数中获取强制参数即可。当然,没有什么可以阻止调用者传递 null,但您的方法也不会。

我发现您的方法的一个大问题是,您要么具有强制参数数量的类组合爆炸,要么强制用户在一个特定的序列中设置参数,这很烦人。

此外,还有很多额外的工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何改进构建器模式? 的相关文章

  • 如何在 IDEA Intellij 上使用 Spring-boot 自动重新加载

    我写了一个基于Spring boot tomcat freemarker的项目 我运行成功 但是每当我修改一些模板和java类时 我必须重新启动服务器或使用Intellij上的 重新加载更改的类 菜单才能使更改生效 浪费很多时间 然后我尝试
  • 将 MouseListener 添加到面板

    我正在尝试将鼠标操作添加到我的面板中 这就是程序应该做的事情 编写一个程序 允许用户通过按三下鼠标来指定一个三角形 第一次按下鼠标后 画一个小点 第二次按下鼠标后 绘制一条连接前两个点的线 第三次按下鼠标后 绘制整个三角形 第四次按下鼠标会
  • 在 Java 正则表达式中获取多个模式的重叠匹配

    我有同样的问题这个链接 https stackoverflow com questions 18751486 matching one string multiple times using regex in java 但有多种模式 我的正
  • 使类只能从特定类实例化

    假设我有 3 节课class1 class2 and class3 我怎样才能拥有它class1只能通过实例化class2 class1 object new class1 但不是 class3 或任何其他类 我认为它应该与修饰符一起使用
  • 如何作为应用程序发布到页面?

    所以 我有一个应用程序 Facebook 应用程序实体 并且我有一个页面 我想使用应用程序通过java代码 通过restfb或任何其他建议 发布到页面 看起来我错过了页面授予应用程序发布权限的阶段 不知道该怎么做 谢谢你们 乌里 您只能 作
  • Java 卡布局。多张卡中的一个组件

    一个组件 例如JLabel 在多张卡中使用CardLayout 目前看来该组件仅出现在它添加到的最后一张卡上 如果有办法做到这一点 我应该吗 这是不好的做法吗 或者有其他选择吗 你是对的 它只出现在 添加到的最后一张卡 中 但这与CardL
  • 在java中将字符串日期转换为美国格式

    我有下面的代码 其中日期为字符串类型 我必须将其设置为美国格式 所以下面我已经展示了它 private static final SimpleDateFormat usOutputDate new SimpleDateFormat MM d
  • 无法从资源加载图片

    So I am trying to load a image file from a resource so that when I export my application into a jar file it could be use
  • 如何将 Java 地图转换为在 Scala 中使用?

    我正在开发一个 Scala 程序 该程序调用 Java 库中的函数 处理结果并生成 CSV 有问题的 Java 函数如下所示 Map
  • 具有 JPA 持久性的 Spring 状态机 - 存储库使用

    我试图弄清楚如何轻松使用 Spring 状态机 包括使用 JPA 进行持久化 这是我正在处理的问题 不兼容的数据类型 工厂和持久性 在程序的某个时刻 我想使用连接到用户的状态机 有用于此目的的存储库 项目spring statemachin
  • Struts 1 到 Spring 迁移 - 策略

    我有一个legacy银行应用程序编码为Struts 1 JSP现在的要求是迁移后端 目前为 MVC to Springboot MVC 后续UI JSP 将迁移到angular Caveats 1 后端不是无状态的 2 会话对象中存储了大量
  • 生成 equals 和 hashcode 时忽略属性

    假设我有一个类 Customer public class Customer private String firstName private String lastName private String doNotAddMeToEqual
  • 正确签名的 JNLP 应用程序无法在 Java 7 中运行

    我有一个 JNLP 应用程序 由于证书过期需要更新 我有一个经过 CA 验证的新证书 我已将新证书导入到我的密钥库中 我已导入完整的证书链 我的构建文件对构建中的 jar 进行签名和时间戳
  • 拆分/标记化/扫描字符串并注意引号

    Java中是否有默认 简单的方法来分割字符串 但要注意引号或其他符号 例如 给定以下文本 There s a man that live next door in my neighborhood and he gets me down Ob
  • 为什么无法从 WEB-INF 文件夹内加载 POSModel 文件?

    我在我的 Web 项目中使用 Spring MVC 我将模型文件放在 WEB INF 目录中 String taggerModelPath WEB INF lib en pos maxent bin String chunkerModelP
  • BadPaddingException:无效的密文

    我需要一些帮助 因为这是我第一次编写加密代码 加密代码似乎工作正常 但解密会引发错误 我得到的错误是 de flexiprovider api exceptions BadPaddingException 无效的密文 in the 解密函数
  • 如何减去两个 XmlGregorianCalendar 对象来创建一个 Duration 对象?

    我想计算两个时间之间的差值XmlGregorianCalendar对象 从而创建一个Duration object 但我还没有找到执行减法的干净方法 你会怎么做 那应该是 DatatypeFactory newDuration xgc2 t
  • 使用 PC/SC 读卡器验证 Ultralight EV1

    我在尝试使用 Java 中的 PC SC 读卡器 特别是 ACR1222L 验证 Ultralight EV1 卡时遇到问题 我能够使用 ISO 14443 3 标签的相应 APDU 在不受保护的标签上进行写入和读取 但是 我找不到运行 P
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • Java中单例的其他方式[重复]

    这个问题在这里已经有答案了 只是我在考虑编写单例类的其他方法 那么这个类是否被认为是单例类呢 public class MyClass static Myclass myclass static myclass new MyClass pr

随机推荐

  • 意外删除表时恢复 cassandra 集群数据

    如您所知 Cassandra 集群具有复制功能 可以防止数据丢失 即使集群中的某些节点发生故障也是如此 但是 如果管理员不小心删除了一个包含大量数据的表 并且该命令已经由集群中的所有副本执行 这是否意味着您丢失了该表并且无法恢复它 有什么建
  • Python PrettyTable:在表格标题上方添加标题

    我有一个生成多个表的脚本 这些表都具有相同的列名和非常相似的数据 到目前为止 我一直通过在每个表之前打印标题来使每个表变得唯一 即 print Results for Method Foo table 1 print Results for
  • 机器人框架中“If语句”的使用

    我们如何在机器人框架中使用if语句 我想仅当关键字满足某些条件时才执行它 否则它会执行其他代码 这在机器人框架用户指南 http robotframework org robotframework latest RobotFramework
  • WT中如何清理内存?

    更新 2013 年 3 月 27 日 您还必须意识到 从 Wt 3 3 0 开始 只有收到请求后才会清除会话 请参阅这个回复 http redmine webtoolkit eu boards 2 topics 5614 r 5615 me
  • NetBeans 模块项目中是否可以依赖 JAR 文件?

    我创建了一个 NetBeans 模块项目 需要添加对我创建的 JAR 文件的依赖项 这可能吗 我只看到添加对其他模块的依赖项的选项 我正在使用 NetBeans 6 5 1 THANKS 模块只能依赖于其他模块 创建引用您的类的库 然后创建
  • 循环遍历动态添加元素的数组

    jQuery 新手 请求帮助解决我无法解决的问题 克隆的表行包含
  • 使用 run-as 命令在 Samsung 4.4.2“程序包未知”上调试本机应用程序

    在尝试通过 Galaxy S4 上的 Eclipse 调试 Android 本机应用程序时 我在 run as 命令中收到 包未知 错误 有一个开放的这说明了与许可相关的问题 data system packages list文件必须是rw
  • NSMutableArray 与 NSArray 哪个更好

    这是一个有点愚蠢的问题 但是如果我想将一个对象添加到数组中 我可以使用两者来完成NSMutableArray and NSArray 我应该使用哪个 NSMutableArray array1 array1 addObject obj NS
  • 当另一个应用程序开始/停止播放音频时,我的应用程序可以收到通知吗?

    我的 iOS 游戏有音乐和音效 我想让用户听自己的音乐来代替游戏的背景音乐 一个简单的解决方案是添加一个新的菜单项来禁用游戏的背景音乐 但是 我想避免创建新的菜单项 除非我确信这种方法对用户来说更糟糕 我目前的做法 将音频会话类别设置为AV
  • 为什么 RNN 需要两个偏置向量?

    In Pytorch RNN 实现 http pytorch org docs master nn html highlight rnn torch nn RNN 有两个偏差 b ih and b hh 为什么是这样 它与使用一种偏差有什么
  • 如何强制 PM2 使用我的应用程序的最新版本?

    我首先调用 PM2pm2 start index js watch ignore watch node modules 然而 尽管告诉它查看我的文件是否有更改然后重新加载 但当我从 git 拉取时 它并没有使用我的应用程序的最新版本 要测试
  • 尽管手机设置了静音模式,但在 Android 通知中播放声音

    我的应用程序正在显示通知 并且当显示通知时 会播放声音 但是当我的手机处于 静音模式 时 不会播放通知 我想 覆盖 音量设置 并在设置了静音模式的情况下播放声音 有办法做到吗 您好 您可以使用 MediaPlayer 作为通知声音 方法是启
  • 如何返回元素的个数?

    我必须编写一个函数 它接受一个整数列表作为参数并返回列表中小于 1 的整数的数量 到目前为止 我所拥有的是一个仅返回列表中的整数个数的函数 我不确定应该在哪里 是否放置 if 语句和计数器以仅返回有多少个整数小于 1 export num
  • HTML 复选框的选中属性的正确值是多少?

    我们都知道如何在 HTML 中形成复选框输入
  • Google Play,发布应用程序更新,“本机平台”问题

    我有一个混合应用程序 我过去曾发布过更新 在当前的更新中 我添加了原生 facebook 登录 这需要在 libs 文件夹下添加 facebook jar 包 现在 当我在 PlayStore 中添加我的 APK 时 一切都很好 除了本机平
  • Dart:在 Windows 上构建时出现“无效参数:路径中存在非法字符”

    我的 index html 文件中的违规行如下 错误报告是 Build error Transform polymer PolymerBootstrapTransformer on myproj frontend web index htm
  • Ping 到存储过程以了解 .net 中的执行是否已完成?

    我必须执行一个存储过程 当我执行该操作时 我必须继续检查 ping 该执行是否完成 我将更新标签 我们在 C 中有什么办法可以做到这一点吗 异步调用存储过程 并让回调更新您的标签 这是一篇关于它的文章 http www devx com d
  • 计算机编程艺术练习题:第 1 章,问题 8

    我正在做 TAOCP 第 1 卷第 3 版的练习 但无法理解以下练习的答案中使用的语法 第 1 章练习 8 Computing the greatest common divisor of positive integers m n by
  • 干预/图像需要文件信息

    我在干预 图像方面遇到问题 Laravel composer install intervention image 2 1 1 requires ext fileinfo gt the requested PHP extension fil
  • 如何改进构建器模式?

    动机 最近我寻找一种方法来初始化复杂的对象 而不需要向构造函数传递大量参数 我尝试使用构建器模式 但我不喜欢这样的事实 即我无法在编译时检查是否确实设置了所有需要的值 传统建造者模式 当我使用构建器模式来创建我的Complex对象 创建更加