两全其美的

使用抽象文档模式的类型安全视图

您如何组织对象? 在本文中,我将介绍一种模式,该模式以无类型的方式在您的系统中组织所谓的名词类,然后使用特征公开数据的类型化视图。 这使得只需少量的牺牲就可以在Java之类的语言中获得JavaScript之类的非类型语言的灵活性。 纳里亚

用户在用户界面中所做的每种配置,表单中的每种选择都需要存储在可从应用程序访问的某个位置。 它需要以一种可以操作的格式存储。 教科书中的示例是为系统中每个名词定义类,并为它们所包含的字段使用getter和setter方法。 做教科书模型的一种更为严肃的方法是为每个名词定义企业bean,并使用注释对其进行处理。 它可能看起来像这样:

siQNe3MEh6TA9QAKcIUf1lA

这些静态模型有局限性。 随着系统的发展,您将需要添加更多字段,更改组件之间的关系,并可能出于不同目的创建其他实现。 你知道这个故事。 突然,每个名词的静态成分不再那么有趣了。 因此,您开始研究其他开发人员。 他们如何解决这个问题? 在JavaScript等非类型化语言中,您可以使用地图来解决此问题。 有关组件的信息可以存储为键值对。 如果一个子系统需要存储一个附加字段,则可以这样做,而无需事先定义该字段。

var myCar = {model: "Tesla", color: "Black"};
myCar.price = 80000; // A new field is defined on-the-fly

它加快了发展速度,但同时付出了巨大的代价。 您会失去类型安全性! 每个真正的Java开发人员的噩梦。 由于您没有使用组件的结构,因此测试和维护也更加困难。 在Speedment进行的最近一次重构中,我们面对静态设计与动态设计的这些问题,并提出了一个称为Abstract Document Pattern的解决方案。

抽象文件模式

swd-IduLEylpsrxRH_ZLVxQ

此模型中的文档类似于JavaScript中的Map。 它包含许多未指定值类型的键值对。 在这个未类型化的抽象文档之上,是许多Traits ,它们表示一个类的特定属性。 特征已使用类型化的方法来检索它们表示的特定值。 名词类只是原始文档接口的抽象基础实现之上的不同特征的并集。 因为一个类可以从多个接口继承,所以可以这样做。

实作

让我们看一下这些组件的来源。

Document.java

public interface Document {Object put(String key, Object value);Object get(String key);<T> Stream<T> children(String key,Function<Map<String, Object>, T> constructor);
}

BaseDocument.java

public abstract class BaseDocument implements Document {private final Map<String, Object> entries;protected BaseDocument(Map<String, Object> entries) {this.entries = requireNonNull(entries);}@Overridepublic final Object put(String key, Object value) {return entries.put(key, value);}@Overridepublic final Object get(String key) {return entries.get(key);}@Overridepublic final <T> Stream<T> children(String key,Function<Map<String, Object>, T> constructor) {final List<Map<String, Object>> children = (List<Map<String, Object>>) get(key);return children == null? Stream.empty(): children.stream().map(constructor);}
}

HasPrice.java

public interface HasPrice extends Document {final String PRICE = "price";default OptionalInt getPrice() {// Use method get() inherited from Documentfinal Number num = (Number) get(PRICE); return num == null? OptionalInt.empty(): OptionalInt.of(num.intValue());}
}

在这里,我们只公开获取价格的吸气剂,但是您当然可以用相同的方法实现一个吸气剂。 这些值始终可以通过put()方法进行修改,但是您面临着将值设置为不同于getter期望的类型的风险。

汽车.java

public final class Car extends BaseDocumentimplements HasColor, HasModel, HasPrice {public Car(Map<String, Object> entries) {super(entries);}}

如您所见,最终的名词类很少,但是您仍然可以使用类型化的吸气剂访问颜色,型号和价格字段。 向组件添加新值就像将其放入地图一样容易,但是除非它是接口的一部分,否则它不会公开。 该模型还适用于分层组件。 让我们看一下HasWheels特性的外观。

HasWheels.java

public interface HasWheels extends Document {final String WHEELS = "wheels";Stream<Wheel> getWheels() {return children(WHEELS, Wheel::new);}
}

就是这么简单! 我们利用以下事实:在Java 8中,您可以将对象的构造函数作为方法引用来引用。 在这种情况下,Wheel类的构造函数仅采用一个参数Map <String,Object>。 这意味着我们可以将其称为Function <Map <String,Object>,Wheel>。

结论

这种模式既有优点,也有缺点。 随着系统的扩展,文档结构易于扩展和构建。 不同的子系统可以通过特征接口公开不同的数据。 根据使用哪个构造函数生成视图,可以将同一地图视为不同类型。 另一个优势是,整个对象层次结构都存在于一个Map中,这意味着可以使用现有的库(例如Google的gson工具 )轻松进行序列化和反序列化。 如果希望数据是不可变的,则只需将内部映射包装在构造函数中的unmodifiableMap()中,即可保护整个层次结构。

一个缺点是它不如常规的bean结构安全。 可以通过多个接口从多个位置修改组件,这可能会使代码的可测试性降低。 因此,在大规模实施此模式之前,应权衡利弊。

  • 如果要查看实际的抽象文档模式示例,请查看Speedment项目的源代码,其中该项目管理有关用户数据库的所有元数据。

翻译自: https://www.javacodegeeks.com/2016/02/the-best-of-both-worlds.html

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

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

相关文章

Windows内核函数

字符串处理 在驱动中一般使用的是ANSI字符串和宽字节字符串&#xff0c;在驱动中我们仍然可以使用C中提供的字符串操作函数&#xff0c;但是在DDK中不提倡这样做&#xff0c;由于C函数容易导致缓冲区溢出漏洞&#xff0c;针对字符串的操作它提供了一组函数分别用来处理ANSI字符…

前端应该关注的2021年UI设计趋势

UI设计趋势几乎每年都在发生变化&#xff0c;变化的原因是人们的审美在变导致的&#xff0c;还是设计越来越人性化。市场上是谁在主导设计趋势&#xff1f;其中原因不得而知&#xff0c;我们先看看究竟有哪些变化&#xff1a;1. 3D插图&#xff08;依然流行&#xff09;3D图像将…

如何让你在开发者工具中查看源代码有语法高亮和暗黑主题的效果

如何让你在Chrome浏览器开发者工具中查看源代码的时候&#xff0c;和在代码编辑器中有同样的代码语法高亮的效果&#xff0c;而且还是深色主题&#xff0c;如果你是深色主题的爱好者就更合你意了。国外的美女开发者为你实现了这样功能的浏览器拓展&#xff0c;她的Github主页&a…

“太空语言”JavaScript编码标准规范指南

喷气推进实验室是 美国国家航空航天局的科研机构。 该实验室JPL开发大部分的软件是用在无人深度太空和其他行星探测的领域。他们拥有著名的 好奇号火星探测器 和 旅行者号探测器 。已经离开太阳系25年&#xff0c;仍然在飞行并提供科学信息。高水平的自动化和长期的任务导致了对…

如何在JUnit 5中替换规则

最近发布的JUnit 5&#xff08;又名JUnit Lambda&#xff09; Alpha版本引起了我的兴趣&#xff0c;在浏览文档时&#xff0c;我注意到规则以及跑步者和阶级规则都消失了。 根据文档&#xff0c;这些部分竞争的概念已被单个一致的扩展模型取代。 多年来&#xff0c; Frank和我…

微页面设计开发指南

一、目标实现左侧&#xff1a;为可用的组件列表&#xff0c;可拖动任一组件到中间的预览区域中间&#xff1a;为页面预览效果页面&#xff0c;选中任一组件&#xff0c;可在右侧进行参数配置右侧&#xff1a;为组件的参数配置&#xff08;选中中间的组件时出现&#xff09;&…

商城商品购买数量增减的完美JS效果

商城商品购买数量增减的完美JS效果 近期在开发一个地方O2O租书项目&#xff0c;使用ASP.NET MVC技术&#xff0c;其中在图书详情页&#xff0c;用户可以输入借阅的数量&#xff0c;这里使用了js来控制数量的增减和校验。 数量一定是数字 点击增减按钮的时候要能自动加1或减1 …

这款插件让你在VSCode上也能答题背单词

在VSCode上也可以在线答题了&#xff0c;插件市场上线了一款答题的插件&#xff0c;免去了去其它网站或者软件的烦恼&#xff0c;代码写累了&#xff0c;随手打开答题功能&#xff0c;换换脑子&#xff0c;或者熟悉两个单词&#xff0c;程序员的别样休闲时光&#xff0c;哈哈&a…

使用Java 8在地图上流式传输

在本文中&#xff0c;我将向您展示如何在标准Java映射上有效地实现Speedment Open Source流&#xff0c;并将Stream接口扩展为MapStream&#xff01; 即使在复杂的情况下&#xff0c;此添加将使保持流的具体性和可读性变得更加容易。 希望这将允许您继续流式传输而不会过早收集…

如何使用python给PDF文件加水印

Python作为编程界最火的语言&#xff0c;能做的事几乎你能想到的它都能干&#xff0c;就连抢茅台都可以&#xff0c;还有什么不行&#xff1f;&#xff01;Python作为脚本编程语言&#xff0c;可以做很多事情。使用Python&#xff0c;你可以轻松地给pdf加上水印。 你可以使用名…

搭建一个redis高可用系统

一、单个实例 当系统中只有一台redis运行时&#xff0c;一旦该redis挂了&#xff0c;会导致整个系统无法运行。 单个实例二、备份 由于单台redis出现单点故障&#xff0c;就会导致整个系统不可用&#xff0c;所以想到的办法自然就是备份&#xff08;一般工业界认为比较安全的备…

SSH连接远程服务器,本地known_hosts文件记录了什么

今天工作时&#xff0c;使用ssh命令远程连接公司的本地服务器时&#xff0c;突然出现以下错误bash-3.2$ ssh argus192.168.200.8 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdroppin…

“全人类的知识宝藏”维基百科迎来了20岁的生日!

维基百科从一个伟大的想法开始&#xff0c;与无数的像你像我一样的阅读者&#xff0c;创作者&#xff0c;捐赠者和粉丝经历了互联网的20年&#xff0c;今天让我们一起为这个属于所有互联网人的成果庆祝一次生日。值此20周年特地为它做了一个主页&#xff1a;https://wikimediaf…

转:智能音箱市场深度报告:怎么大家都在抢这个两亿小蛋糕?

原文链接&#xff1a;http://www.sohu.com/a/199335366_115978 智能音箱是今年最热的智能硬件项目之一。目前&#xff0c;智能音箱已经有了比较成熟的技术方案和模式思路&#xff0c;但消费市场似乎依然秉持着比较谨慎的态度。智能音箱市场上的主流产品都有什么思路&#xff1f…

Tailwindcss尤大神都fork了,是未来的趋势?

最近Tailwindcss频繁出现在我的视野里&#xff0c;从单词拼写中看&#xff0c;多多少少与css有点关系。近几年是JS框架大行其道&#xff0c;CSS方面少有新的框架出现。昨天突然看到尤大神在Github上的动态&#xff0c;fork了该项目&#xff0c;看来马上要火的节奏啊&#xff01…

JUnit 5 –架构

现在我们知道如何设置JUnit 5并使用它编写一些测试 &#xff0c;下面让我们看一下。 在本文中&#xff0c;我们将讨论JUnit 5架构以及采用这种方式的原因。 总览 这篇文章是有关JUnit 5的系列文章的一部分&#xff1a; 设定 基本 建筑 条件 注射 … JUnit 4 忽略Hamcre…

前端程序员书桌上不可缺少的CSS书籍

作为前端&#xff0c;CSS不仅要会&#xff0c;而且要精通&#xff0c;随着各种浏览器规范参差不齐和网页交互多元化的趋势越来越复杂&#xff0c;前端程序员必须要将CSS基础知识打牢。由于现在的框架越来越多&#xff0c;导致很大一部分程序员的工作只是拿着现成的组件布局&…

nodejs 进阶:图片缩小

demo 效果&#xff1a; 代码&#xff1a; /*** Created by ZXW on 2017/10/30.*/ var fs require(fs); var gm require(gm);gm(./不饿.jpg).resize(50, 50,"!").write(./不饿1.jpg, function (err) {if (!err) console.log(done);});2017-10-30 22:10:46转载于:ht…

可能是最先出来的关于介绍使用Vue3的一本书

Vue3 release版本已发布有几个月了&#xff0c;不少公司都已经开始使用vue3开发项目了&#xff0c;市场上的主流的框架如&#xff1a;Vant&#xff0c;Element UI&#xff0c;Taro也都发布了支持Vue3的版本。Vue3很多的开发优势自不必再说&#xff0c;学习上手vue3已经成为每个…

CSGL

glShadeModel void glShadeModel(GLenum mode) GL_FLAT/【GL_SMOOTH】 着色技术选择 glClearDepth GL.glClearDepth(depth); glClearDepth&#xff1a;设置深度缓存的清除值 参数 depth 指定清除深度缓存时使用的深度值。 说明 本函数指定用glClear清除深度缓存时所使用的深度值…