这是几天前在与Ruby Web应用程序Codexia一起工作时发现的一个新想法。 我必须从PostgreSQL获取数据行并将对象返回给客户端。 对于我来说一直是一个问题,如何在不将对象变成DTO的情况下做到这一点。 这是我找到并命名的解决方案:Veil Objects。
![](https://i-blog.csdnimg.cn/blog_migrate/402067447262b9667ed73fc04030c792.png)
假设我从PostgreSQL获取项目列表:
该方法exec()
上@pgsql
(我使用的是pgtk宝石)返回数组哈希值 ,它是这样的,如果我们把它们转换成JSON:
使fetch()
方法返回一个对象数组,而不是一个哈希数组,将是很棒的。 所以我的班级Project
看起来像这样:
它非常适合单项目操作:
这里有两个SQL请求不是什么大问题。 但是,如果我将哈希表的列表转换为这样的项目,则会遇到严重的性能问题:
在性能方面,这将杀死我:
此代码将生成太多冗余SQL请求。 在执行SELECT * FROM project
,我们将往返于PostgreSQL以获取几毫秒前的数据。
许多人可能建议的最简单,最显而易见的解决方案是将检索到的哈希值封装到Project
对象中。 换句话说,将Project
变成DTO ,即数据的持有者。 好吧,在这种情况下,我们甚至可能不需要对象,而是可以将Hash与数据一起返回。 但这不是我们希望设计面向对象软件的方式。 我们要处理对象,而不是数据结构。 而且,与此同时,我们不希望对象足够愚蠢以至于无法返回数据库以获取第二秒之前的相同数据。 这是我提出的解决方案:
这个新的Veil
对象是Project
的装饰器。 它的行为类似于Project
,但其中的一些方法已重新定义: name()
和author()
。 调用它们时,调用不会到达封装的Project
。 相反,将返回Veil
存储的数据。
之所以将其称为“面纱”,是因为它的行为类似于“面纱”:仅在调用其他未设置的其他方法之前返回预设数据。 如果发生这种情况,将穿透面纱,并且Veil
对象变得完全透明,从而发送所有方法调用。
因此,DTO的效率与OOP的优雅相结合。
我在yegor256 / codexia中使用了这些新的面纱对象,因此您可以看到它们的工作原理。
PS我还创建了一个Unpiercable
类,该类的行为与Veil
完全一样,但是永远不能被刺穿。 当您不希望与该对象发生任何修改数据的交互并且仅希望预先计算其某些方法时,此功能非常有用。
翻译自: https://www.javacodegeeks.com/2020/05/veil-objects-to-replace-dtos.html