这个想法是几周前在设计“ Generator”类时想到的,该类必须将输入发送给封装的Writer 。 实际上,它是Builder模式。 但是,规则有些复杂,用户必须以某种方式调用add...()方法,才能正确生成输出。

不用说,我不喜欢让一个BuilderImpl类在内部设置和验证各种标志,以便知道什么时候被允许的选择。 解决方案是构建一个有限状态机 ,因为构建者的界面很流畅。 像往常一样,在这篇文章中,我将通过一个例子来说明。

汤姆和杰瑞(Tom&Jerry)–《老鼠麻烦》,威廉·汉纳(William Hanna)和约瑟夫·巴贝拉(Joseph Barbera)

假设我们要实现一个DateBuilder ,它将以经典的dd.mm.yyyy格式(可能还带有其他类型的分隔符,不仅. )生成一个String 。 为了简单起见,我们将只关注格式,而忽略诸如一个月中的天数,leap年之类的情况。首先是界面:

public interface DateBuilder {DateBuilder addDay(final Integer day);DateBuilder addMonth(final Integer month);DateBuilder addYear(final Integer year);DateBuilder addSeparator(final String sep);String build();}

上面的接口将有五个实现: StringDateBuilder (公共入口点), ExpectSeparatorExpectMonthExpectYearExpectBuild (这四个包均受程序包保护,对用户不可见)。 StringDataBuilder看起来像这样:

public final class StringDateBuilder implements DateBuilder {private final StringBuilder date = new StringBuilder();@Overridepublic DateBuilder addDay(final Integer day) {this.date.append(String.valueOf(day));return new ExpectSeparator(this.date);}@Overridepublic DateBuilder addMonth(final Integer month) {throw new UnsupportedOperationException("A day is expected first! Use #addDay!");}@Overridepublic DateBuilder addYear(final Integer year) {throw new UnsupportedOperationException("A day is expected first! Use #addDay!");      }@Overridepublic DateBuilder addSeparator(final String sep) {throw new UnsupportedOperationException("A day is expected first! Use #addDay!");}@Overridepublic String build() {throw new UnsupportedOperationException("Nothing to build yet! Use #addDay!");}}

我相信您已经明白了:其他四个实现将处理它们自己的情况。 例如, ExpectSeparator将从addSeparator(...)之外的所有方法中引发异常,在该方法中,它将分隔符附加到StringBuilder并返回ExpectMonth的实例。 最后,这台机器的最后一个节点将是ExpectBuild (在添加年份之后由ExpectYear返回),它将抛出build()之外所有方法的异常。

这种设计帮助我将代码对象保持较小,没有标志和if/else分支。 与往常一样,上面的每个类都易于测试,并且通过切换返回的实现,可以轻松更改构建器的行为。

当然,我不是唯一想到这些的人:先生。 尼古拉斯·弗兰克(NicolasFränkel)就在上个月在这里写下了这个想法。 但是,我觉得有必要带走我的两分钱,因为我不完全喜欢他的例子:他为构建器的节点使用了不同的接口,以保持构建器的安全性和防白痴性(例如,甚至不允许用户查看addMonthbuild方法(如果他们不应该使用的话)。 我不同意这一点,因为这意味着我需要管理更多的代码,此外,客户端将与构建者的逻辑相结合。 我宁愿只强制用户到学习如何使用生成器(它不应该是他们的一个大的努力,因为他们应该搭上一个最简单的单元测试任何异常,对不对? 吧... )

我也找到了这篇文章 ,它提供了更广泛,更理论上的解释,并不一定与Builder模式相关联-如果您考虑一下,这种方法可以用于任何必须根据其内部状态更改其行为的对象。

翻译自: https://www.javacodegeeks.com/2018/12/builder-fail-fast-state-machine.html

生成器作为(快速失败)状态机相关推荐

  1. 咱们来聊聊快速失败和安全失败

    一:快速失败(fail-fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...

  2. Spring Cloud Alibaba 2.2.6发布:新增Nacos注册快速失败的配置

    7月12日消息,Spring Cloud Alibaba新版本2.2.6发布,该版本适配Spring Cloud Hoxton.SR9. 下面一起来看看该版本内容: 特性增强 Nacos 支持服务注册 ...

  3. fail safe java_Java中快速失败(fail-fast)和安全失败(fail-safe)的区别?

    快速失败(fail-fast): 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exception ...

  4. fail-fast(快速失败/报错机制)-ConcurrentModificationException

    2019独角兽企业重金招聘Python工程师标准>>> 一.fail-fast机制(快速报错机制) 这是<Java编程思想>中关于快速报错机制的描述 Java容器有一种保 ...

  5. Java - Java集合中的快速失败Fail Fast 机制

    文章目录 什么是 fail-fast 源码解读 Itr 为什么对集合的结构进行修改会发生并发修改异常-源码分析 修改方法之 remove 修改方法之 add 案例分享 [案例一] [案例二] [案例三 ...

  6. 快速失败Vs安全失败(Java迭代器附示例)

    译者:java达人-卍极客 英文出处:Java Concept Of The Day 英文链接:http://javaconceptoftheday.com/(点击文末阅读原文前往) 转载请标注以上声 ...

  7. 快速失败(fail-fast)和安全失败(fail-safe)

    我们都接触 HashMap.ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的:而 java.util.concurrent 包下的类都是安全失败,比如:Concu ...

  8. java-List集合的源码分析(数据结构方面,源码注释方面),迭代器快速失败机制

    List实现了Collection接口,产生三个子类:ArrayList,LinkedList,Vector 文章包含解释方面: 数据结构方面, 源码注释方面&迭代器快速失败机制 方面1-基于 ...

  9. java 登陆验证失败_使用Java 8流进行快速失败的验证

    java 登陆验证失败 我已经失去了看过使用快速失败验证代码状态的代码的次数,方法如下: public class PersonValidator {public boolean validate(P ...

  10. java返回fail_Java集合中的fail-fast(快速失败)机制详解

    简介 我们知道Java中Collection接口下的很多集合都是线程不安全的, 比如 java.util.ArrayList不是线程安全的, 因此如果在使用迭代器的过程中有其他线程修改了list,那么 ...

最新文章

  1. ormlite android studio,OrmLite-android入门体验
  2. 2019中职计算机大赛,2019年广西职业院校技能大赛中职组《计算机平面设计》赛项竞赛规程.pdf...
  3. 这群“未来零售之星” 收到了一份意义非凡的新年大礼
  4. 复平面中的点集预备知识
  5. 利用集合对数据进行去重操作
  6. 【渝粤教育】国家开放大学2018年秋季 0221-22T数字电子电路 参考试题
  7. EtherCAT总线伺服速度控制功能块(H5U PLC)
  8. 软件测试的艺术读书笔记<转>
  9. 利用jquery 实现 京东商城 左则商品分栏
  10. 【Linux】一步一步学Linux——hostid命令(246)
  11. 超好用的私人珍藏网站,送给你了!
  12. 人机融合智能时代的人心思考
  13. Apache网页优化
  14. 如何用计算机录视频,怎么用电脑录视频,详细操作教程分享给大家
  15. 原生安卓去除网络叉号
  16. Eclipse小技巧--修改@auther和去掉//TODO
  17. ORA-3136 WARNING: inbound connection timed out
  18. 玉柴spn码故障对照表_玉柴电控柴油机故障代码及读码方法2
  19. decoration
  20. 深耕MySQL - SQL必知必会

热门文章

  1. codeforces1473 E.Minimum Path(分层图最短路)
  2. 【模板】吉老师线段树
  3. Scala与Java差异(三)之函数
  4. PL/SQL之JOB用法 (定时跑数据)
  5. 跟我学 Java 8 新特性之 Stream 流(二)关键知识点
  6. MySQL date_sub()函数
  7. SpringMVC @Transactional的陷井大坑引发No Session found for current thread
  8. EL表达式和Jstl常见的用法
  9. 第三章选择结构(一)
  10. 最全三大框架整合(使用映射)——Emp.hbm.xml