10个步骤的筛选器模式

过滤器是仅在某些情况下应应用的模式。 在原始帖子中 ,我提供了一个非常简单的示例,旨在演示如何应用它。 在这篇文章中,我提供了一个更详细的示例,该示例还旨在说明何时以及为什么应用它。

介绍

该职位包括以下10个简短步骤 。 在每个步骤中,我介绍了以下两种类型的要求

  • B- *业务要求(由产品所有者提供→ 无可争辩
  • S- *解决方案要求(从解决方案的选择→ 有争议的结果中得出)

我提出了一个Java模型,模型可以满足到目前为止介绍的要求。 我一直这样做,直到Filterer成为首选解决方案。

所以,让我带你踏上这段旅程……

步骤1:问题检测器

要求#1

假设企业要求一种算法来检测英文文本中的语法和拼写问题

例如:

  • 文字: 您很了解。 →要检测的问题:
    1. migth (类型:拼写)
  • 文字: 我没有注意放松。 →要检测的问题:
    1. 注意 (类型:拼写)
    2. 松散 (类型:语法)
  • 文字: 我一直注意到它很松。 →要检测的问题:∅

这是第一个业务需求B-1 )。


B-1会议的最简单模型可以是:

  • 输入 :纯文本
  • 输出 :问题列表,每个问题提供:
    • 输入文字内的偏移量

这是我们的第一个解决方案要求S-1 )。

Java模型#1

我们可以将S-1建模为:

interface IssueDetector {// e.g. text: "You migth know it."List<Issue> detect(String text);
}

哪里:

interface Issue {int startOffset(); // e.g. 4 (start of "migth")int endOffset(); // e.g. 9 (end of "migth")IssueType type(); // e.g. SPELLING
}
enum IssueType { GRAMMAR, SPELLING }

提交1 。

步骤2:机率

要求#2

但是,要实现以这种确定性方式工作的真实IssueDetector相当困难:

  • 问题(概率P = 100%
  • 无问题(概率P = 0%

相反, IssueDetector应该是概率性的 :

  • 可能的问题(概率P =?

我们可以通过引入概率阈值( PT )来保持问题/非问题的区别:

  • 问题(概率P≥PT ),
  • 非问题(概率P <PT )。

尽管如此,仍然值得修改模型以保留概率( P )–例如,在渲染 (更高的概率→更突出的渲染)中很有用。

综上,我们额外的解决方案要求是:

  • S-2 :支持发布概率( P );
  • S-3 :支持概率阈值( PT )。

Java模型2

通过将probability()添加到Issue我们可以满足S-2

interface Issue {// ...double probability();
}

我们可以通过在IssueDetector添加probabilityThreshold IssueDetector probabilityThreshold来满足S-3IssueDetector

interface IssueDetector {List<Issue> detect(String text, double probabilityThreshold);
}

提交2 。

步骤3:可能的问题

要求#3

假设业务需要

  • B-3 :使用英语语言家校对的文本测试所有问题检测器(=无概率)。

这样的校对文本 (或: 测试用例 )可以定义为:

  • 文字,例如您shuold知道。
  • 预期的问题,例如
    1. shuold (类型:拼写)

因此,我们的解决方案要求是:

  • S-4 :支持预期的问题(=没有可能性)。

Java模型3

我们可以通过提取子接口( ProbableIssue )来满足S-4

interface ProbableIssue extends Issue {double probability();
}

并从IssueDetector返回ProbableIssue

interface IssueDetector {List<ProbableIssue> detect(...);
}

提交3 。

步骤4:明智的文字

要求#4

假使,假设:

  1. 所有测试用例都在外部定义(例如,在XML文件中);
  2. 我们要创建一个参数化的JUnit测试 ,其中参数是作为Stream 提供的 测试用例

通常,一个测试用例代表了一种我们可以称之为按问题发布的文本 (一种文本及其问题)。

为了避免将有问题的文本建模为Map.Entry<String, List<Issue>> (含糊不清,表示抽象不足),让我们介绍另一个解决方案要求

  • S-5 :支持明智的文本。

Java模型4

我们可以将S-5建模为:

interface IssueWiseText {String text(); // e.g. "You migth know it."List<Issue> issues(); // e.g. ["migth"]
}

这使我们可以简单地定义测试用例Stream ,如下所示:

  • Stream<IssueWiseText>

代替

  • Stream<Map.Entry<String, List<Issue>>>

提交4 。

步骤5:预期覆盖率

要求#5

假设业务需要

  • B-4 :报告一系列测试用例的 预期 问题范围

为了简单起见,将问题的覆盖范围定义为:

发行时
─────────────
文字长度

实际上, 问题的覆盖范围可能代表一些非常复杂的业务逻辑

Java模型5

我们可以使用基于Collector的方法处理B-4

static double issueCoverage(Stream<? extends IssueWiseText> textStream) {return textStream.collect(IssueCoverage.collector());
}

Collector基于具有两个可变字段的Accumulator

int totalIssueLength = 0;
int totalTextLength = 0;

对于每个IssueWiseText ,我们增加:

totalIssueLength += issueWiseText.issues().stream().mapToInt(Issue::length).sum();
totalTextLength += issueWiseText.text().length();

然后我们将问题覆盖范围计算为:

(double) totalIssueLength / totalTextLength

提交5 。

步骤6:取得覆盖

要求#6

假设业务需要

  • B-5 :报告获得了整个测试集的问题覆盖率

“获得”是指“使用检测到的问题进行计算”。 现在事情开始变得有趣了!

首先,由于IssueCoverage表示业务逻辑 ,所以我们不应该重复它:

  • S-6 :重用问题覆盖代码。

其次,由于该方法采用Stream<? extends IssueWiseText> Stream<? extends IssueWiseText> ,我们需要为ProbableIssue建模一个IssueWiseText

  • S-7 :支持概率问题文本。

我在这里只看到两个选择:

  1. 参数化 : IssueWiseText<I extends Issue>
  2. 子类型化 : ProbabilisticIssueWiseText extends IssueWiseText

参数Java模型#6

S-7的参数模型很简单-我们在IssueWiseText需要<I extends Issue> IssueWiseText <I extends Issue> (一个有界类型参数 ):

interface IssueWiseText<I extends Issue> {String text();List<I> issues();
}

这个模型有缺点(例如类型擦除 ),但是很简洁。

我们还可以修改IssueDetector来返回IssueWiseText<ProbableIssue>

此外,我们的测试用例Stream可能会变成Stream<IssueWiseText<Issue>> (尽管IssueWiseText<Issue>颇有争议)。

提交6a 。

子类型化Java模型#6

另一个选择是选择子类型 (它有其自身的缺点,其中最大的缺点可能是重复 )。

S-7的子类型模型采用返回类型协方差 :

interface ProbabilisticIssueWiseText extends IssueWiseText {@OverrideList<? extends ProbableIssue> issues();
}

IssueWiseText中的issues()必须成为上限 ( List<? extends Issue> )。

我们还可以修改IssueDetector来返回ProbabilisticIssueWiseText

提交6b 。

步骤7:按问题类型过滤

要求#7

假设业务需要

  • B-6 :按问题类型报告问题范围

我们可以通过接受Predicate <? super Issue>类型的额外参数来支持它Predicate <? super Issue> Predicate <? super Issue>IssueType参数通常太窄)。

但是,直接在IssueCoverage支持它会使业务逻辑复杂化( 提交7a' )。 相反,我们宁愿将已过滤IssueWiseText实例提供给IssueCoverage

我们如何进行过滤? “手动”执行操作(调用new )会给实现带来不必要的耦合(我们甚至还不了解它们)。 这就是为什么我们让IssueWiseText进行过滤的原因(我觉得这个逻辑属于那里):

  • S-8 :支持在IssueWiseTextIssue进行IssueWiseText

换句话说,我们希望能够说:

换句话说,我们希望能够说:

IssueWiseText ,按Issue筛选自己!

参数Java模型#7

在参数模型中,我们将以下filtered方法添加到IssueWiseText<I>

IssueWiseText<I> filtered(Predicate<? super I> issueFilter);

这使我们满足B-6的要求:

return textStream.map(text -> text.filtered(issue -> issue.type() == issueType)).collect(IssueCoverage.collector());

提交7a 。

子类型化Java模型#7

在子类型模型中,我们还添加了filtered方法(与上面的方法非常相似):

IssueWiseText filtered(Predicate<? super Issue> issueFilter);

这让我们以与上述相同的方式遇到了B-6

提交7b 。

步骤8:按机率筛选

要求#8

假设业务需要

  • B-7 :按最小概率报告问题的覆盖范围

换句话说,企业希望知道概率分布如何影响问题的覆盖范围。

现在,我们希望运行IssueDetector与许多不同的概率阈值(PT),因为这将会是非常低效的。 相反,我们将只运行一次( PT = 0 ),然后以最低的概率继续丢弃问题,以重新计算问题的覆盖范围。

但是,为了能够按概率进行过滤,我们需要:

  • S-9 :支持在概率问题文本中按ProbableIssue进行过滤。

参数Java模型#8

在参数模型中,我们不需要更改任何内容。 我们可以满足B-7的要求:

return textStream.map(text -> text.filtered(issue -> issue.probability() >= minProbability)).collect(IssueCoverage.collector());

提交8a 。

子类型化Java模型#8

在子类型化模型中,这比较困难,因为我们需要在ProbabilisticIssueWiseText一个额外的方法:

ProbabilisticIssueWiseText filteredProbabilistic(Predicate<? super ProbableIssue> issueFilter);

让我们满足B-7的要求:

return textStream.map(text -> text.filteredProbabilistic(issue -> issue.probability() >= minProbability)).collect(IssueCoverage.collector());

提交8b 。


对我来说, ProbabilisticIssueWiseText这种额外方法非常令人不安(请参阅此处 )。 这就是为什么我提议…

步骤9:筛选器

要求#9

由于子类型模型中的常规过滤是如此“不一致”,因此让我们使其统一:

  • S-10 :在问题型文本的子类型模型中支持统一过滤。

换句话说,我们希望能够说:

ProbabilisticIssueWiseText ,用ProbableIssue过滤自己(但是与IssueWiseText本身通过Issue过滤自己一样)!

据我所知,这只能通过Filterer Pattern实现 。

子类型化Java模型#9

因此,我们将通用 Filterer应用于IssueWiseText

Filterer<? extends IssueWiseText, ? extends Issue> filtered();

以及ProbablisticIssueWiseText

@Override
Filterer<? extends ProbabilisticIssueWiseText, ? extends ProbableIssue> filtered();

现在,我们可以通过调用以下内容进行统一过滤:

text.filtered().by(issue -> ...)

提交9 。

步骤10:检测时间

到这个时候,您必须想知道如果参数化模型这么简单的话,为什么还要打扰子类型化模型。

因此,最后一次,我们假设业务需要

  • B-8 :报告检测时间 (=检测给定文本中所有问题所花费的时间)。

参数Java模型#10

我仅看到将B-8合并到参数模型中的两种方法:1)组成,2)子类型化。

参数Java模型#10的组成

涂抹组合物很容易。 我们介绍IssueDetectionResult

interface IssueDetectionResult {IssueWiseText<ProbableIssue> probabilisticIssueWiseText();Duration detectionTime();
}

并修改IssueDetector以将其返回。

提交10a 。

参数Java模型#10的子类型化

应用子类型需要更多的工作。 我们需要添加ProbabilisticIssueWiseText<I> *

interface ProbabilisticIssueWiseText<I extends ProbableIssue> extends IssueWiseText<I> {Duration detectionTime();// ...
}

并修改IssueDetector以返回ProbabilisticIssueWiseText<?>

提交10a' 。

*请注意,我在ProbabilisticIssueWiseText上保留了<I> ,以便不以危险的方式将参数化与子类型化相关联 。

子类型化Java模型#10

使用纯子类型模型,合并B-8非常容易。 我们只是将detectionTime()添加到ProbabilisticIssueAwareText

interface ProbabilisticIssueWiseText extends IssueWiseText {Duration detectionTime();// ...
}

提交10b 。

结论

没有时间详细讨论了(该帖子已经比我预期的要长)。

但是,与其他解决方案Filterer ,我更喜欢纯子类型化(因此更喜欢Filterer ),因为:

  1. 具有组合的参数化使我没有通用的超类型(在某些情况下,这是一个问题);
  2. 具有子类型的参数化具有太多的自由度。

我说“太多自由度”,我只需要:

  • IssueAwareText<?>
  • ProbabilisticIssueAwareText<?>
  • IssueAwareText<Issue> (有争议)

但在代码中,我也会遇到(根据经验说!):

  • IssueAwareText<? extends Issue> IssueAwareText<? extends Issue> (冗余上限)
  • IssueAwareText<ProbableIssue>
  • IssueAwareText<? extends ProbableIssue> IssueAwareText<? extends ProbableIssue> (为什么不ProbabilisticIssueAwareText<?> ?)
  • ProbabilisticIssueAwareText<? extends ProbableIssue> ProbabilisticIssueAwareText<? extends ProbableIssue> (冗余上限)
  • ProbabilisticIssueAwareText<ProbableIssue>

所以对我来说太混乱了。 但是,如果您真的对此主题感兴趣,请查看“ 复杂子类型与参数化” (不过请注意,它甚至比这篇文章还要长!)。

感谢您的阅读!

翻译自: https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html

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

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

相关文章

android 网络调试工具,安卓网络调试助手

安卓网络调试助手源码是一款专门为专业人士准备的安卓网络调试软件&#xff0c;安卓网络调试助手apk支持各种进制的转换发生和多种端口协议&#xff0c;让用户操作起来更加方便&#xff0c;安卓网络调试助手源码有着专业的操作流程&#xff0c;帮助用户快速上手&#xff0c;就算…

android版本8.1.0和9的区别,安卓8.1和9.0的区别是什么

安卓8.1和9.0的主要差别是&#xff1a;流畅度、耗电量、功能等等方面的不同。在手机配置足够的情况下&#xff0c;9.0要比8.1更流畅和省电&#xff0c;它可以同时让后台保持更多APP&#xff0c;每个APP运行的时候更加流畅&#xff0c;其新的智能电量管理功能、暗黑模式让手机更…

看到一个沙粒世界:再一次你好世界

“看到一个沙粒中的世界”&#xff0c;我们很可能会看到最简单的“ Hello World”中的世界&#xff0c;所以我们开始吧&#xff0c;再一次向世界问好。 我猜所有的Java课程&#xff0c;教程都是从这个著名的Hello World程序开始的&#xff0c;这是我可以在没有IDE的帮助下编写…

[渝粤教育] 西南科技大学 中国现代文学 在线考试复习资料

中国现代文学——在线考试复习资料 一、单选题 1.不属于“五四”时期的“问题小说”作家的是( )。 A.冰心 B.庐隐 C.刘呐鸥 D.王统照 2.巴金小说《家》中的觉新是( )。 A.顽固的封建卫道者 B.腐朽堕落者 C.有新思想的懦弱者 D.与封建思想大胆斗争的反抗者 3.《画梦录》的作者…

[渝粤教育] 西南科技大学 中学英语教材教法 在线考试复习资料

中学英语教材教法——在线考试复习资料 一、单选题 1.关于写作评估以下说法正确的是? A.写作评估既要有结果评估,也要有过程评估 B.写作教学评估有写长法又有写短法 C.课堂评估的作用仅为监控学生 D.课堂评估与课堂的具体教学内容有关,可以使用统一的评估模式 2.以下哪种方式…

moreunit_MoreUnit与MoreUnit

moreunit就在一年多以前&#xff0c;我写了一篇关于在Eclipse中使用JUnit的文章。 评论者之一推荐MoreUnit &#xff0c;以进一步提高测试效率。 尝试一下让我感到很高兴&#xff0c;并且我的自主神经系统立即记住了该插件的键盘快捷键…… 另外&#xff0c;在使用MoreUnit一段…

[渝粤教育] 西南科技大学 人力资源管理 在线考试复习资料(1)

人力资源管理——在线考试复习资料 一、单选题 1.实施工作轮换方案之前要做好的工作不包括( ) A.复查每一个连续在同一职业岗位上于了5年以上.特别是更长时间的、正处于职业中期的员工(包括经理在内) 的人事文件 B.评价这些员工的工作,认清其工作专长,了解其个人特征、才干等 C…

android 获取 meid 代码,Android 各个版本获取IMEI、MEID

public class IMEIUtil {/*** 获取默认的imei 一般都是IMEI 1** param context* return*/public static String getIMEI1(Context context) {//优先获取IMEI(即使是电信卡) 不行的话就获取MEIDreturn getImeiOrMeid(context, 0);}/*** 获取imei2** param context* return*/publ…

JMetro版本5发布

Java的第5版JavaFX主题JMetro刚刚发布。 这是此版本中的新功能&#xff1a; 新的文本区域明暗风格&#xff1b; 现有控件样式的一些更改&#xff1b; 新CSS变量称为accent_color。 顾名思义&#xff0c;它允许您定义JMetro控件中使用的强调颜色。 已经进行了很大的重构&am…

[渝粤教育] 西南科技大学 会计学原理 在线考试复习资料(1)

会计学原理——在线考试复习资料 一、单选题 1.资产负债表是反映企业( )财务状况的会计报表。 A.某一特定日期 B.一定时期内 C.某一月份内 D.某一年份内 2.某企业本期盘亏的材料已查明原因,属于自然损耗,批准处理时应编制的会计分录( )。 A.借记“待处理财产损溢”,…

android 开发 矩形截屏插件,Android 上如何实现矩形区域截屏

对屏幕进行截屏并裁剪有两种方式&#xff1a;早截图和晚截图。早截图&#xff0c;就是先截取全屏&#xff0c;再让用户对截取到的图片进行修改;与之相对的&#xff0c;晚截图&#xff0c;就是先让用户在屏幕上划好区域&#xff0c;再进行截图和裁剪。其实两者并没有什么太大的区…

[渝粤教育] 西南科技大学 供应链管理 在线考试复习资料

供应链管理——在线考试复习资料 一、单选题 1.人们设置库存的目的,不包括以下哪种? A.增加固定资产 B.防止缺货 C.保持生产连续性 D.快速满足订货需求 2.费希尔(Fisher)按市场需求模式将产品分为两类,即功能性产品和创新性产品。下面属于功能性产品的是: A.时装 B.石油 C.手…

[渝粤教育] 西南科技大学 信息组织与检索 在线考试复习资料2021版

信息组织与检索——在线考试复习资料2021版 一、单选题 1.要求两个关键词至少有一个出现在检索结果中需使用的操作符是( )。 A. ND B. OR C. ND NOT D. NEAR 答案:看左边查询 2.要求两个关键词都必须出现在检索结果中需使用的操作符是( )。 A. ND B. OR C. ND NOT D. NE…

Android布局怎么画图形,Android开发者的图形化布局

图形化布局编辑器允许你通过拖放来创建UI。在早期版本的ADT中&#xff0c;图形化布局编辑器并不是很有帮助&#xff0c;幸运的是&#xff0c;最新版本非常强大&#xff0c;可以用来创建复杂的包含有复合组件以及动画的布局。(1)Configuration下拉菜单让你可以改变当前布局展示的…

java注释类型_Java 8类型注释

java注释类型Lambda表达式是迄今为止Java 8讨论最多和最受促进的功能。虽然我同意Lambda是一个很大的改进&#xff0c;但我认为其他一些Java 8功能由于Lambda的炒作而有所欠缺。 在这篇文章中&#xff0c;我想展示另一个来自Java 8的出色特性的示例&#xff1a;Type Annotation…

[渝粤教育] 西南科技大学 公共组织学 在线考试复习资料

公共组织学——在线考试复习资料 一、单选题 1.从沟通媒介自身的丰富性程度看,排在第一位的应该是( ) A.电话 B.电子邮件 C.面对面地交谈 D.文件 2.“韦伯认为,以古老的传统、神圣不可侵犯的信念,以及对其下属行使权力的人的地位的合法性为基础的权力属于( ) A.合理–合法型…

[渝粤教育] 西南科技大学 刑事诉讼法学 在线考试复习资料

刑事诉讼法学——在线考试复习资料 一、单选题 1.传唤、拘传持续的时间不得超过十二小时;案情特别重大、复杂,需要采取拘留、逮捕措施的,传唤、拘传持续的时间不得超过( )小时。 A.12 B.24 C.48 2.无期徒刑的执行机关是?( ) A.公安机关 B.监狱 C.检察机关 D.人民法院 3.讯问…

android studio简易记账本,Android记账本

十分感谢徐老师用心制作的这个视频&#xff0c;我学到了很多&#xff0c;再次感谢。这里贴一下我对着这个视频写的代码&#xff1a;https://github.com/supertian007/ImoocDaily&#xff0c;欢迎大家参考、或指出问题。记录一下学习过程中遇到的几个问题&#xff1a;1. 视频的b…

Java可选参数

在Java类中设计方法时&#xff0c;某些参数对于其执行而言可能是可选的。 无论是在DTO&#xff0c;胖模型域对象还是简单的无状态服务类中&#xff0c;可选方法参数都是常见的。 从本文中&#xff0c; 您将学习如何在Java中处理可选参数 。 我们将专注于常规方法&#xff0c;带…

[渝粤教育] 西南科技大学 单片机原理与应用 在线考试复习资料(2)

单片机原理与应用——在线考试复习资料 一、单选题 1.信息能够同时双向传送的是( )。 A.并行通信 B.单工串行通信 C.半双工串行通信 D.全双工串行通信 2.T89S52单片机片内有( )个定时器/计数器。 A.1 B.2 C.3 D.4 3.串口通信时,每秒传送120个字符,数据格式为1位起始位、8位数…