具有空对象模式的 DAO

Posted

技术标签:

【中文标题】具有空对象模式的 DAO【英文标题】:DAO with Null Object Pattern 【发布时间】:2017-02-26 04:31:40 【问题描述】:

阅读后: 有效的 Java(见第 43 条) - Joshua Bloch 干净的代码(不要返回 Null) - Bob 大叔 Avoiding != null statements Null Object pattern

我正在寻找一个问题的答案,即当搜索最终是针对非集合对象不存在的实体时,DAO 应该返回什么。 通过使用空数组或 emptyList 方法,集合对象确实可以。但是对于非收藏品,它可能会更难。另一种解决方案是永远不要返回 null,而是使用 Null Object 模式。 但我不知道如何将 Null Object 模式与 DAO 集成,我真的很高兴看到 Null Object 模式和 DAO 模式的完美集成,尤其是对于 model(dto) 对象返回的情况。

我将不胜感激并欢迎任何最佳设计模式、方案和建议。

【问题讨论】:

返回Optional 有帮助吗? 如果您设置为不使用 null,也可以抛出异常。 @ChiefTwoPencils,是的,但是我遇到了这个dzone.com/articles/java-8-optional-avoid-null-and,至于 cmets,这还不是最佳实践,空对象模式仍然是最好的主意。 @chrylis,我希望 null 是合同条款的有效响应的情况;和 NullObject 模式正在返回一个对象,该对象与您的填充对象(用户)的签名相匹配,其余代码可以确定将返回一个空对象(EmptyUser)。它背后的整个想法是 object.getName() 永远不会返回 null 而是返回一些您可以检查的条目,即 if(user.getName().equals("e'); drop table Students;") then //我们有空对象(或者在这种情况下是小 Bobby 放置表) 【参考方案1】:

确实,引入null 引用可能是编程语言历史上最严重的错误之一,即使它的创建者Tony Hoare 称其为他的十亿美元错误

根据您的Java 版本,以下是null 的最佳替代方案:

1。 Java 8及以上

Java 8 开始,您可以使用java.util.Optional

下面是一个示例,说明如何在您的情况下使用它:

public Optional<MyEntity> findMyEntity() 
    MyEntity entity = // some query here
    return Optional.ofNullable(entity);

2。之前Java 8

Java 8 之前,您可以使用来自 Google Guavacom.google.common.base.Optional

下面是一个示例,说明如何在您的情况下使用它:

public Optional<MyEntity> findMyEntity() 
    MyEntity entity = // some query here
    return Optional.fromNullable(entity);

【讨论】:

dzone.com/articles/java-8-optional-avoid-null-and ,我看到这个关于 Optional 的网站,但你的例子非常好。我想知道你更喜欢 Optional 而不是 Null 对象模式来处理空值? 是的,我绝对更喜欢Optional,它更通用,它已被甲骨文和谷歌采用,这两家世界上最大的 IT 公司都给予了很多赞誉。我什至会说 Null Object Pattern 在 Java 中不再有意义,它已经过时了,Optional 是未来,如果你稍微检查一下 Java 9 中的新功能,你会看到 Oracle 让 Optional 消失了更进一步,阅读this 使用Optional,表示返回值的基数是0或1,所以它给出了一个明确的描述,可以没有值,让调用者决定如何处理它跨度> 这很有用,但我想知道我们是否应该在 DAO 层中也使用 Optional?我的意思是返回值,它应该是 Optional 吗?还是应该在更高层,如服务?顺便问一下,restful services 的返回值如何? @Shilan 我的答案就是为什么不在你的 DAO 界面中使用它?【参考方案2】:

您需要做的就是返回一个空对象 - 比如说您在 DAO 中的客户条目,例如

if (result == null) return new EmptyUser();

其中 EmptyUser 扩展了 User 并向 getter 调用返回适当的条目,以允许您的其余代码知道它是一个空对象(id = -1 等)

一个小例子

public class User 
    private int id;
    private String name;
    private String gender;
    public String getName() 
       //Code here
    
    public void setName() 
       //Code here
    


public class EmptyUser extends User 

    public int getId() 
       return -1;
    

    public String getName() 
       return String.Empty();
   


public User getEntry() 
   User result = db.query("select from users where id = 1");
   if(result == null) 
       return new EmptyUser();
   
   else 
       return result;
    

【讨论】:

是的,这种情况下它是空对象模式,但您能否提供一些模式图并提供 EmptyUser(NullObject) 类的完整代码?假设 EmptyUser 类中有 10 个字段。【参考方案3】:

根据我的经验,在实际场景中,应该返回一个返回 null 的单个实体实际上要么是数据不一致错误,要么是缺少数据。在这两种情况下,真正最好的做法是创建并抛出你自己的DataNotFoudException快速失败

我正在使用 mybatis 作为 ORM,最近我开始编写一些理论上的单结果映射器选择作为返回列表并验证检查 dao 中返回的数据量,并在返回的数量与 dao 的方法假设不匹配时抛出异常。效果很好。

【讨论】:

感谢您的回答,但有时我希望 null 是有效响应的情况,对于这种情况,我想通过自定义消息和一些导航来控制用户。特别是在组合框值显示及其主设置案例中。 抛出异常仍然是一种选择。您可以在堆栈中的任何位置捕获它。但这仅适用于异常情况,因此如果您真的希望查询返回 null,那么只需使用 null 或 Optional。

以上是关于具有空对象模式的 DAO的主要内容,如果未能解决你的问题,请参考以下文章

空对象设计模式与空对象检查

空对象模式

设计模式空对象模式

php实现空对象模式

空对象模式

空对象模式