生成器作为(快速失败)状态机
这个想法是几周前在设计“ 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
(公共入口点), ExpectSeparator
, ExpectMonth
, ExpectYear
和ExpectBuild
(这四个包均受程序包保护,对用户不可见)。 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)就在上个月在这里写下了这个想法。 但是,我觉得有必要带走我的两分钱,因为我不完全喜欢他的例子:他为构建器的节点使用了不同的接口,以保持构建器的安全性和防白痴性(例如,甚至不允许用户查看addMonth
或build
方法(如果他们不应该使用的话)。 我不同意这一点,因为这意味着我需要管理更多的代码,此外,客户端将与构建者的逻辑相结合。 我宁愿只强制用户到学习如何使用生成器(它不应该是他们的一个大的努力,因为他们应该搭上一个最简单的单元测试任何异常,对不对? 吧... )
我也找到了这篇文章 ,它提供了更广泛,更理论上的解释,并不一定与Builder模式相关联-如果您考虑一下,这种方法可以用于任何必须根据其内部状态更改其行为的对象。
翻译自: https://www.javacodegeeks.com/2018/12/builder-fail-fast-state-machine.html
生成器作为(快速失败)状态机相关推荐
- 咱们来聊聊快速失败和安全失败
一:快速失败(fail-fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...
- Spring Cloud Alibaba 2.2.6发布:新增Nacos注册快速失败的配置
7月12日消息,Spring Cloud Alibaba新版本2.2.6发布,该版本适配Spring Cloud Hoxton.SR9. 下面一起来看看该版本内容: 特性增强 Nacos 支持服务注册 ...
- fail safe java_Java中快速失败(fail-fast)和安全失败(fail-safe)的区别?
快速失败(fail-fast): 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exception ...
- fail-fast(快速失败/报错机制)-ConcurrentModificationException
2019独角兽企业重金招聘Python工程师标准>>> 一.fail-fast机制(快速报错机制) 这是<Java编程思想>中关于快速报错机制的描述 Java容器有一种保 ...
- Java - Java集合中的快速失败Fail Fast 机制
文章目录 什么是 fail-fast 源码解读 Itr 为什么对集合的结构进行修改会发生并发修改异常-源码分析 修改方法之 remove 修改方法之 add 案例分享 [案例一] [案例二] [案例三 ...
- 快速失败Vs安全失败(Java迭代器附示例)
译者:java达人-卍极客 英文出处:Java Concept Of The Day 英文链接:http://javaconceptoftheday.com/(点击文末阅读原文前往) 转载请标注以上声 ...
- 快速失败(fail-fast)和安全失败(fail-safe)
我们都接触 HashMap.ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的:而 java.util.concurrent 包下的类都是安全失败,比如:Concu ...
- java-List集合的源码分析(数据结构方面,源码注释方面),迭代器快速失败机制
List实现了Collection接口,产生三个子类:ArrayList,LinkedList,Vector 文章包含解释方面: 数据结构方面, 源码注释方面&迭代器快速失败机制 方面1-基于 ...
- java 登陆验证失败_使用Java 8流进行快速失败的验证
java 登陆验证失败 我已经失去了看过使用快速失败验证代码状态的代码的次数,方法如下: public class PersonValidator {public boolean validate(P ...
- java返回fail_Java集合中的fail-fast(快速失败)机制详解
简介 我们知道Java中Collection接口下的很多集合都是线程不安全的, 比如 java.util.ArrayList不是线程安全的, 因此如果在使用迭代器的过程中有其他线程修改了list,那么 ...
最新文章
- ormlite android studio,OrmLite-android入门体验
- 2019中职计算机大赛,2019年广西职业院校技能大赛中职组《计算机平面设计》赛项竞赛规程.pdf...
- 这群“未来零售之星” 收到了一份意义非凡的新年大礼
- 复平面中的点集预备知识
- 利用集合对数据进行去重操作
- 【渝粤教育】国家开放大学2018年秋季 0221-22T数字电子电路 参考试题
- EtherCAT总线伺服速度控制功能块(H5U PLC)
- 软件测试的艺术读书笔记<转>
- 利用jquery 实现 京东商城 左则商品分栏
- 【Linux】一步一步学Linux——hostid命令(246)
- 超好用的私人珍藏网站,送给你了!
- 人机融合智能时代的人心思考
- Apache网页优化
- 如何用计算机录视频,怎么用电脑录视频,详细操作教程分享给大家
- 原生安卓去除网络叉号
- Eclipse小技巧--修改@auther和去掉//TODO
- ORA-3136 WARNING: inbound connection timed out
- 玉柴spn码故障对照表_玉柴电控柴油机故障代码及读码方法2
- decoration
- 深耕MySQL - SQL必知必会
热门文章
- codeforces1473 E.Minimum Path(分层图最短路)
- 【模板】吉老师线段树
- Scala与Java差异(三)之函数
- PL/SQL之JOB用法 (定时跑数据)
- 跟我学 Java 8 新特性之 Stream 流(二)关键知识点
- MySQL date_sub()函数
- SpringMVC @Transactional的陷井大坑引发No Session found for current thread
- EL表达式和Jstl常见的用法
- 第三章选择结构(一)
- 最全三大框架整合(使用映射)——Emp.hbm.xml