当前位置: 首页 > 知识库问答 >
问题:

生成器模式验证-有效的Java

姜森
2023-03-14

在Effective Java(第二版)的第2项中,作者提到了以下关于在使用构建器时对参数施加不变量的内容:

在将参数从构建器复制到对象后,必须检查它们,并在对象字段而不是构建器字段上检查它们(项目 39)。如果违反任何不变量,则生成方法应引发非法状态异常(项 60)。

这是否意味着构建方法创建目标对象后,应该将其传递给验证例程以进行任何所需的验证?

另外,有人能解释一下这背后的原因吗?

共有2个答案

梁盛
2023-03-14

构建器的build()方法通常会调用它正在构建的类的私有构造函数。这就是为什么构建器通常被实现为静态嵌套类,因此它们可以访问私有构造函数。构造函数是验证发生的地方。即使您没有使用构建器模式,构造函数也有责任确保对象在创建时处于有效状态。构造函数应该创建防御副本(EJ第39项)并验证新对象的字段,而不是构建器的字段,因为在复制字段时构建器可能会发生突变。

万楷
2023-03-14

对象验证是使用构建器创建对象的一个组成部分。虽然您可以有一个单独的例程来执行验证,但不需要这样的分离:验证代码可以是执行构建的函数的一部分。换句话说,您可以这样做

TargetObject build() {
    TargetObject res = new TargetObject();
    res.setProperty1();
    res.setProperty2();
    validate(res); // This call may throw an exception
    return res;
}

void validate(TargetObject obj) {
    if (...) {
        throw new IllegalStateException();
    }
}

或者这个:

TargetObject build() {
    TargetObject res = new TargetObject();
    res.setProperty1();
    res.setProperty2();
    if (...) {
        throw new IllegalStateException();
    }
    return res;
}

重要的是验证发生在目标对象构建之后,而不是之前。换句话说,您需要验证对象的状态,而不是构建者的状态。

 类似资料:
  • 问题内容: 我有一些需要在C++中模仿的示例Python代码。我不需要任何特定的解决方案(例如基于协同例程的收益解决方案,尽管它们也是可接受的答案),我只需要以某种方式重现语义即可。 python 这是一个基本的序列生成器,显然太大了,无法存储实例化版本。 目标是维护上述序列的两个实例,并以半锁步的方式在块上进行迭代。在下面的示例中,使用对的序列来初始化缓冲区,然后重新生成 相同的精确序列 并再次

  • 问题 你需要准备一个复杂的、多部分的对象,你希望操作不止一次或有不同的配置。 解决方案 创建一个生成器封装对象的产生过程。 Todo.txt 格式提供了一个先进的但还是纯文本的方法来维护待办事项列表。手工输入每个项目有损耗且容易出错,然而 TodoTxtBuilder 类可以解决我们的麻烦: class TodoTxtBuilder constructor: (defaultParamet

  • 亦称: 建造者模式、Builder 意图 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 问题 假设有这样一个复杂对象, 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中; 甚至还有更糟糕的情况, 那就是这些代码散落在客户端代码的多个位置

  • 我必须向客户提供上传他自己的JSON模式的可能性。 是否有方法验证用户提供的JSON模式是有效的JSON模式,而不仅仅是数据? 我在这个库中使用Javahttps://github.com/networknt/json-schema-validator 更新: 我有以下模式: 我需要知道这是否是一个有效的JSON模式,而不是JSON数据。此处提供了一个JSON数据示例:

  • 我尝试用Maven发生器原型生成新的Magnolia模块 mvn组织。阿帕奇。专家插件:maven原型插件:2.4:generate-DarchetypeCatalog=https://nexus.magnolia-cms.com/content/groups/public/ Archetype抛出了一个异常 [警告]读取原型目录时出错https://nexus.magnolia-cms.com/

  • 问题内容: 我想将一个Web服务URL请求表示为一个对象,并发现在继承层次结构中可能有很多通用参数。一个请求可以有很多参数,一些是必选参数,而其他是可选参数,我相信Bloch的Builder模式是一个不错的选择,它可以使用流畅的接口模拟命名参数。 具体来说,我正在设计Google Maps网络服务API,该API具有常规的网络服务请求 和是必填参数,也是必填参数。还有一个可选参数。 每个服务都有其