资讯专栏INFORMATION COLUMN

空对象模式

刘厚水 / 3306人阅读

摘要:概述在这个快速教程中,我们将看一下对象模式,这是设计模式的一个特例,一个经常被我们遗忘的特例。对象模式的目的是最小化这种空检查。何时使用空对象模式我们应该使用对象模式,否则客户端会检查只是为了跳过执行或执行默认操作。

概述

在这个快速教程中,我们将看一下Null对象模式,这是设计模式的一个特例,一个经常被我们遗忘的特例。我们将描述它的目的以及我们何时应该考虑使用它。

像往常一样,我们还将提供一个简单的代码示例。

空对象模式
在大多数面向对象的编程语言中,我们会考虑不进行null引用,为此我们经常被迫写空检查:
Command cmd = getCommand();
if (cmd != null) {
    cmd.execute();
}

有时,如果此类if语句的数量变多,则代码的可读性会变得很差,难以阅读且容易出错。这是Null对象模式可以派上用场的时候。

Null对象模式的目的是最小化这种空检查。相反,我们可以识别null行为并将其封装在客户端代码所期望的类中。这样我们就不再需要处理空引用的特殊处理。

我们可以简单地处理null对象,就像处理实际包含一些更复杂的业务逻辑的给定类型的任何其他实例一样,以此来保持代码的清洁。

由于null对象不应具有任何状态,因此无需多次创建相同的实例。因此,我们经常将null对象实现为单例

Null Object Pattern的UML图

让我们直观地看一下模式:

我们可以看到,会有以下参与者:

客户端需要AbstractObject的实例

AbstractObject定义客户期望的执行逻辑- 它还可以包含实现类的共享逻辑

RealObject实现了AbstractObject并提供了真实的行为

NullObject实现AbstractObject并提供do nothing行为

案例

现在我们已经清楚地了解了这个理论,让我们看一个例子。

假设一个场景,有一个消息路由器模块。每条消息都应分配有效的优先级。我们的系统应该将高优先级消息路由到SMS网关,而具有中等优先级的消息应该路由到JMS队列。

但是,有时会出现“未定义”或空优先级的消息。这些消息应该从进一步处理中丢弃。

首先,我们将创建路由器接口:

public interface Router {
    void route(Message msg);
}

接下来,让我们创建上述接口的两个实现 - 负责路由到SMS网关的接口以及将消息路由到JMS队列的接口:

public class SmsRouter implements Router {
    @Override
    public void route(Message msg) {
        // implementation details
    }
}
public class JmsRouter implements Router {
    @Override
    public void route(Message msg) {
        // implementation details
    }
}

最后,让我们实现我们的null对象

public class NullRouter implements Router {
    @Override
    public void route(Message msg) {
        // do nothing
    }
}

我们现在准备将所有部分组合在一起。让我们看看示例客户端代码的外观如何:

public class RoutingHandler {
    public void handle(Iterable messages) {
        for (Message msg : messages) {
            Router router = RouterFactory.getRouterForMessage(msg);
            router.route(msg);
        }
    }
}

我们可以看到,无论RouterFactory返回什么实现,我们都以相同的方式处理所有Router对象。这使我们能够保持代码的清洁和可读性。

何时使用空对象模式

我们应该使用Null对象模式,否则客户端会检查null只是为了跳过执行或执行默认操作。 在这种情况下,我们可以将do nothing逻辑封装在空对象中,并将其返回给客户端而不是空值。这样,如果给定实例为null,则客户端代码不再需要知道 。

这种方法也遵循一般的面向对象原则。

为了更好地理解何时应该使用Null对象模式,让我们假设我们必须实现CustomerDao接口,定义如下:

public interface CustomerDao {
    Collection findByNameAndLastname(String name, String lastname);
    Customer getById(Long id);
}

如果没有客户匹配提供的搜索条件,大多数开发人员将从findByNameAndLastname()返回Collections.emptyList()。这是遵循Null对象模式的一个很好的例子。

相反,getById()应返回具有给定id的客户。调用此方法的人希望获得特定的客户实体。如果不存在这样的客户,我们应该显式返回null以表示提供的ID存在问题。

与所有其他模式一样,我们需要在盲目实现Null对象模式之前考虑我们的特定用例。否则,我们可能会无意中在代码中引入一些很难找到的错误。

结论

在本文中,我们了解了Null对象模式是什么以及何时可以使用它。我们还实现了一个设计模式的简单示例。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73825.html

相关文章

  • 复习笔记(新手向) - JS对象声明的几种方式

    摘要:二用操作符构造对象属性名属性值属性名属性值属性名属性值属性名属性值方法名方法名首先用创建一个空对象,然后用多条语句给对象添加属性方法。他的写法与三用函数声明的方式构造对象比较像,但是稍有不同。 -- 新手向知识,就不用ES6写法了。 一、字面量声明 var obj = { 属性名1 : 属性值, 属性名2 : 属性值, 属性名3 : 属性...

    davidac 评论0 收藏0
  • 设计模式总结

    摘要:,命令模式,将行为请求者和行为实现者解耦,将行为抽象为对象。解释器模式,迭代器模式,将集合对象的存储数据和遍历数据职责分离。即将遍历的责任交给迭代器返回的迭代器,迭代器。 设计模式总结 创建型:除了直接new来实例化对象外,提供了多种隐藏创建逻辑的生成对象的方法 结构型:通过对象和类的组合,得到新的结构和功能 行为型:解决对象之间的通行和功能职责分配 详细分类 工厂 简单工厂...

    quietin 评论0 收藏0
  • Java23种设计模式与J2EE设计模式

    摘要:这个模式感觉一一般和工厂模式一起使用的比较多比较方便结构型模式这些设计模式关注类和对象的组合。设计模式这些设计模式特别关注表示层。 设计模式的的六大原则: 学习设计模式之前最好先了解一下设计模式的设计原则: 1. 开闭原则(open close principle) 开放即指对扩展开放,对修改关闭 简而言之,就是扩展功能的时候应该尽量的不修改原有的代码。 2. 里氏代换原则(lisko...

    andot 评论0 收藏0
  • 面对对象编程

    摘要:也就是说,构造函数内部,指的是一个新生成的空对象,所有针对的操作,都会发生在这个空对象上。上面代码中,构造函数的语句,返回的是一个新对象。 一、创建对象 1.构造函数var Vehicle = function () { this.price = 1000;}; var v = new Vehicle();v.price // 1000 new命令本身就可以执行构造函数,所以后面的构...

    leeon 评论0 收藏0
  • JavaScript之 new 命令

    摘要:命令执行时,构造函数内部的,就代表了新生成的实例对象,表示实例对象有一个属性,值是。因此,应该非常小心,避免不使用命令直接调用构造函数。命令返回这个对象,而不是对象。JavaScript 面向对象编程的基础知识篇 1 。 1. 概述 面向对象编程(Object Oriented Programming,缩写为 OOP)是目前主流的编程范式。 那么,对象(object)到底是什么? 对象是单...

    desdik 评论0 收藏0

发表评论

0条评论

刘厚水

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<