变压器图案

Transformer模式是Java(以及可能仅具有使用场所差异和不变参数类型的其他OO语言)的设计模式,可帮助子类型层次结构内的对象将自己流畅地转换为任何类型的对象。

语境

我一直在关注与Jim Laskey发行的JDK-8203703相关的OpenJDK线程( 9月18-21日 , 11月12-13日, 11月13-30日, 12月3-4日 ),然后我想到了一个主意。 让我回顾一下讨论的相关部分。

String.transform的建议

根据JDK-8203703的提案可归结为以下新增内容:

public final class String implements /*...*/ CharSequence {// ...public <R> R transform(Function<? super String, ? extends R> f) {return f.apply(this);}// ...
}

如您所见,此方法仅自身调用给定的Function即可。 但是,它对于链接实用程序方法非常有用,例如Apache Commons的 StringUtils中的方法:

String result = string.toLowerCase().transform(StringUtils::stripAccents).transform(StringUtils::capitalize);

通常,我们必须写:

String result = StringUtils.capitalize(StringUtils.stripAccents(string.toLowerCase()));

考虑CharSequence.transform

在某个时候,艾伦·贝特曼(Alan Bateman) 提出了在CharSequence中潜在定义transform 的问题 :

<R> R transform(Function<? super CharSequence, ? extends R> f)

这将具有能够在任何CharSequence上应用基于CharSequence的实用程序方法(例如StringUtils.isNumeric )的好处,例如:

boolean isNumeric = charSequence.transform(s -> StringUtils.defaultIfBlank('0')).transform(StringUtils::isNumeric);

但是,正如RémiForax所指出的 ,此签名的问题在于:

  • 如果它是由String 继承的:大多数实用程序方法都将String作为参数–这样的方法将不起作用(例如StringUtils :: capitalize ),
  • 如果它被String 覆盖 :由于以下原因,无法进行有用的覆盖:
    • Function<? super String, R>

结果, CharSequence.transform的主题已被删除。

问题

总而言之,问题在于能够进行转换

  • 一个CharSequence ,使用Function即需要CharSequenceObject? super CharSequence ),
  • 一个String ,使用接受String或其任何父类型( ? super String )的Function

当我在这里查看这些下 限时 ,我意识到我已经看到了这种问题(参见Filterer Pattern )。

因此,这个问题归结为:如何协变地指定Function 界。

Java不支持逆变参数类型 ,并且它的语法也没有提供一种方法来协变( ? extends )指定在单个声明中绑定的逆变( ? super )。 然而,有可能做到这一点在两个分开的宣言,通过中间辅助类型的装置。

假设我们要为泛型Function<? super T, ? extends R> Function<? super T, ? extends R> Function<? super T, ? extends R> ,我们需要:

  • 将上面的Function参数移动到参数为T辅助接口中
  • 将此辅助接口与上限 ( ? extends T )一起用作返回类型。

变压器接口

我定义了这样的帮助程序接口(我称之为Transformer ),如下所示:

@FunctionalInterface
interface Transformer<T> {<R> R by(Function<? super T, ? extends R> f);
}

可转换的接口

定义了Transformer ,我们可以定义以下称为Transformable基本接口:

interface Transformable {Transformer<?> transformed();
}

该接口本身并不能做很多事情,但我将其视为以下方面的规范

  • 子类型实现者 :它提醒他们使用适当的上限覆盖已transformed方法,并加以实现,
  • 子类型用户 :提醒他们可以调用transformed().by(f)

总结起来,这对( TransformerTransformable )让我们替换:

  • obj.transform(function)
  • 使用: obj.transformed().by(function)

样例实施

回到String之前,让我们看看实现这两个接口有多么容易:

class Sample implements Transformable {@Overridepublic Transformer<Sample> transformed() {return this::transform; // method reference}private <R> R transform(Function<? super Sample, ? extends R> f) {return f.apply(this);}
}

如您所见,所需要的只是对transform的方法引用 。

transform方法被设为私有,因此当子类型定义自己的(适当地, 下界 ) transform时,它们之间不会发生冲突。

上下文中的解决方案

上下文中的实现

它如何应用于CharSequenceString ? 首先,我们将CharSequence扩展为Transformable

public interface CharSequence extends Transformable {// ...@OverrideTransformer<? extends CharSequence> transformed();// ...
}

然后,我们transformedString实现transformed ,返回对public transform方法的方法引用(已在JDK 12中添加 ):

public final class String implements /*...*/ CharSequence {// ...@Overridepublic Transformer<String> transformed() {return this::transform;}// ...
}

请注意,我们对transformed的返回类型进行了协变更改: Transformer<? extends CharSequence> Transformer<? extends CharSequence>Transformer<String>

相容性风险

我认为添加CharSequence.transformed的兼容性风险很小。 仅对于那些已经具有无参数transformed方法的CharSequence子类,它可能会破坏向后兼容性(这似乎不太可能)。

上下文中的用法

对于使用String不会改变,因为有呼吁没有一点transformed().by()transform()

但是,通用CharSequence的用法将需要诉诸transformed().by()因为它可能有很多实现,因此transform方法必须是private

boolean isNumeric = charSequence.transformed().by(s -> StringUtils.defaultIfBlank('0')).transformed().by(StringUtils::isNumeric);

性能

如果您不熟悉JVM (最常表示HotSpot )及其JIT编译器的工作方式,那么您可能想知道这种明显的额外对象创建( Transformer in transformed )是否不会影响性能。

幸运的是,由于有了转义分析 *和标量替换 ,该对象从未在堆上分配。 答案是:不会,不会。

* 此Wikipedia条目包含错误的陈述:“ 因此,编译器可以安全地在堆栈上分配这两个对象。 ”正如 AlekseyShipilёv解释的那样 ,Java不会在堆栈上分配整个对象。

基准测试

如果您需要证明,这里有一些基准(使用AlekseyShipilёv出色的JMH基准线束 )。 因为我不能(容易),添加必要的方法,以String ,我创建了一个简单的包装过String ,并实现了在它之上的标杆。

基准测试toLowerCase()操作:

  • 在两个字符串上:
    1. "no change" (无操作)
    2. "Some Change"
  • 使用三种通话类型:
    1. 直接(基准)
    2. transform()
    3. transformed().by()

您可以在GitHub gist中找到此基准测试的完整源代码。

结果如下(在Oracle JDK 8上运行,花费了50分钟):

Benchmark                            (string)  Mode  Cnt   Score   Error  UnitsTransformerBenchmark.baseline       no change  avgt   25  22,215 ± 0,054  ns/op
TransformerBenchmark.transform      no change  avgt   25  22,540 ± 0,039  ns/op
TransformerBenchmark.transformed    no change  avgt   25  22,565 ± 0,059  ns/opTransformerBenchmark.baseline     Some Change  avgt   25  63,122 ± 0,541  ns/op
TransformerBenchmark.transform    Some Change  avgt   25  63,405 ± 0,196  ns/op
TransformerBenchmark.transformed  Some Change  avgt   25  62,930 ± 0,209  ns/op

如您所见,对于这两个字符串,这三种调用类型之间没有性能差异。

摘要

我意识到, Transformable可能太“奢侈”了,无法真正将其纳入JDK。 实际上,即使仅由CharSequenceString返回的Transformer也不值得。 这是因为对CharSequence的一元运算似乎并不常见(例如StringUtils仅包含少数几个)。

但是,我发现“ Transformer和“ Transformable的基本概念很诱人。 因此,我希望您喜欢阅读,并在某些情况下会发现它很有用

翻译自: https://www.javacodegeeks.com/2019/02/transformer-pattern.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 分库分表_大众点评订单系统分库分表实践

原大众点评的订单单表早就已经突破两百G&#xff0c;由于查询维度较多&#xff0c;即使加了两个从库&#xff0c;优化索引&#xff0c;仍然存在很多查询不理想的情况。去年大量抢购活动的开展&#xff0c;使数据库达到瓶颈&#xff0c;应用只能通过限速、异步队列等对其进行保护…

[渝粤教育] 西南科技大学 经济学概论 在线考试复习资料

经济学概论——在线考试复习资料 一、单选题 1.可持续发展战略的核心内容是正确处理? A.农、轻、重之间的比例关系 B.第一、二、三产业之间的比例关系 C.经济发展与人口、资源、环境之间的关系 D.积累与消费之间的比例关系 2.调整和优化产业结构就是要? A.在国民经济各部门之…

多模光纤收发器购买时需要注意什么问题?

光纤收发器是光通讯产品的一类&#xff0c;它一般应用在以太网电缆无法覆盖、必须使用光纤来延长传输距离的实际网络环境中&#xff0c;同时在帮助把光纤最后一公里线路连接到城域网和更外层的网络上也发挥了巨大的作用。现如今&#xff0c;随着光通信产业的高速发展&#xff0…

[渝粤教育] 西南科技大学 计算机网络应用基础 在线考试复习资料2021版(1)

计算机网络应用基础——在线考试复习资料2021版 一、单选题 1. 在数字通信中广泛采用CRC循环冗余码的原因是CRC可以( )。 A. 检测出一位差错 B. 检测并纠正一位差错 C. 检测出多位突发性差错 D. 检测并纠正多位突发性差错 答案:看左边查询 2.为了保证连接的可靠性,TCP通常…

[渝粤教育] 西南科技大学 高级语言程序设计(Java) 在线考试复习资料

高级语言程序设计&#xff08;Java&#xff09;——在线考试复习资料 一、单选题 1.下列哪一个包给出了Runnable接口的定义?( ) A.iava.util B.java.io C.java.lang D.java.sql 2.下列( )属于Java线程同步方法。 A.joiny( ) B.run( ) C.wait( ) D.stroy( ) 3.下列方法中可以…

cd mysql 权限不够_.bash_profile权限不够_cdmysql权限不够

mac环境下创建bash_profile文件并写入内容_IO690x477 - 118KB - JPEGmac下创建bash_profile的问题? - Mac - 知乎585x366 - 22KB - PNG如何设置bash profile格式599x366 - 38KB - JPEG如何设置bash profile格式599x366 - 38KB - JPEG.bash_profile .bashrc profile文件的作用的…

POE交换机产品如何设计防雷保护?

在POE供电系统实际应用中&#xff0c;有很多受电设备AP或移动基站的基站AP与天线&#xff0c;经常要安装于建筑物的高端点&#xff0c;因此这些受电设备也成为遭受雷击的高发点。所以&#xff0c;对于这类的数据网络中心&#xff0c;不仅要考虑建设良好的直击雷防护网与良好的接…

【渝粤教育】电大中专学前儿童科学教育 (5)作业 题库

作业视频教务托管&#xff0c;壹叁路路贰陆陆壹〇肆〇 学前儿童科学教育的学习重点是( ) A.技术的概念 B.学前儿童科学教育的内涵 C.科学的概念 D.学前儿童科学教育的概念 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2.以认识自然为目的的是&#xff08; &#…

lucene 多个分词查找_使用Lucene的新FreeTextSuggester查找长尾建议

lucene 多个分词查找Lucene的“ 建议”模块提供了许多有趣的自动建议实现&#xff0c;以便在用户将每个字符输入搜索框时为他们提供实时搜索建议。 例如&#xff0c; WFSTCompletionLookup将所有建议及其权重编译到一个紧凑的有限状态传感器中 &#xff0c;从而可以对基本建议…

【渝粤教育】电大中专幼儿园课程论 (7)作业 题库

作业视频教务托管&#xff0c;壹叁路路贰陆陆壹〇肆〇 以下哪种不是按照课程的表现形态划分的&#xff08; &#xff09; A.活动课程 B.分科课程 C.分科课程 D.显性课程 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;未作答 2.如果幼儿园课程的教育理念强调儿童的发…

32linux下安装mysql5.7_Linux系统下以RPM方式安装mysql-5.7.9

1在开始安装之前&#xff0c;我们先来一小段官方文档&#xff0c;看下图。图中英文翻译过来就是&#xff1a;从MySQL5.7.4起&#xff0c;以RPM包的方式安装后的MySQL的部署默认是安全的&#xff0c;并且有这些特点&#xff1a;在大多数情况下&#xff0c;你只需要安装MySQL-ser…

【渝粤教育】电大中专新媒体营销实务 (7)作业 题库

1.依产生的先后顺序&#xff0c;当前媒体可分为四类&#xff1a;报纸、杂志等纸质平面媒体、广播媒体、电视媒体、互联网媒体。该说法&#xff08; &#xff09; A.正确 B.错误 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2.第四媒体发展到宽带互联网阶段成为&a…

PoE交换机的4种连接方法

POE也被称为基于局域网的供电系统或有源以太网&#xff0c;有时也被简称为以太网供电&#xff0c;一个完整的POE系统包括供电端设备和受电端设备两部分。可能会有一些朋友对poe供电有一些疑问&#xff0c;这个在之前也有很多朋友问到过&#xff0c;那么&#xff0c;今天就由飞畅…

【渝粤教育】电大中专电商运营实操 (23)作业 题库

电子商务最重要的是&#xff08; &#xff09; A商务 B网站 C信息技术 D货物 正确 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2下列关于电子商务的特点叙述错误的是&#xff08; &#xff09; A全球性 B简单的电子化支付手段 C交易环节多&#xff0c;营销成本高 D信…

带有NetBeans 10的Java EE

Apache NetBeans项目正在逐步形成。 10.0版于2018年12月27日发布。 下载版中列出了自9.0版以来添加的主要功能。 对我个人而言&#xff0c;最重要的功能是JDK 11支持。 那么&#xff0c;Java EE呢&#xff1f; 在将所有NetBeans源从Oracle转移到Apache并合并到Apache NetBean…

【渝粤教育】电大中专职业健康与安全 (3)作业 题库

试卷答案 1根据系统安全工程的观点&#xff0c;危险是指系统中存在导致发生不期望后果的可能性超过了&#xff08; &#xff09; A极限 B人们的承受程度 C危险度 D安全系数 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2对职工来说&#xff0c;安全是&#xff0…

POE交换机供电原理及工作过程

POE指的是在现有的以太网Cat.5布线基础架构不作任何改动的情况下&#xff0c;在为一些基于IP的终端&#xff08;如IP电话机、无线局域网接入点AP、网络摄像机等&#xff09;传输数据信号的同时&#xff0c;还能为此类设备提供直流电的技术.就是支持以太网供电的交换机。那么&am…

datagridview控件读写mysql数据库表格的方法_c# datagridview表格控件常用操作

1) 行右键菜单private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e){if (e.Button MouseButtons.Right){if (e.RowIndex > 0){//若行已是选中状态就不再进行设置if (dataGridView1.Rows[e.RowIndex].Selected false){dataGridView…

【渝粤教育】电大中专计算机常用工具软件 (2)作业 题库

1下列类型的软件中&#xff0c;功能没有任何限制且又不需要付费的是&#xff08;&#xff09;。 A共享软件 B正版软件 C免费软件 D试用软件 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;D 2在常见的软件版本号中,Professional表示()。 A测试版 B专业版 C家庭版 D免…

PoE交换机可以当普通交换机使用吗?

PoE交换机是一种新型的多功能交换机&#xff0c;随着PoE交换机的广泛应用&#xff0c;人们对PoE交换机有了一定的了解。然而&#xff0c;很多人认为PoE交换机可以自行发电&#xff0c;这种说法并不正确&#xff0c;通常所讲的PoE交换机供电指的是PoE交换机通过网线来给其他设备…