0

我正在构建一个 API。它的功能之一是执行一些资源分析(想象一个文档、URI 或 DB,不重要什么)并返回一个 POJOList<Finding>所在的位置。Finding我希望一旦从 API 返回不可变,所有数据都由 API 返回,但是,为了方便客户端 Finding,我希望有一个方法。setUserNote(String)

这样做的原因是客户端获得了Findings 的列表,它可以在处理它们的同时setUserNote将自己的数据保存在对象本身中,就像一个普通的笔记一样。我认为这将是一种简洁的便利,而不是客户端必须扩展Finding只是添加一个变量或将其封装为实例变量,然后ExtendedFinding.someMethod() { return this.finding.someMethid(); }对于 Finding. 此外,至少可以说,对于客户端来说,从他从 API 中获取的内容中进行构建会很ExtendedFinding麻烦Finding。这就是为什么我打算只给他们一个他们可以方便使用的字段。

问题:

  1. 这是糟糕的设计吗?为什么?我以前从未做过这样的事情,也从未见过 API 类带有任意数据持有者变量以方便客户使用。

  2. 假设这是一个糟糕的设计。什么是适用的设计模式,可以轻松地传播 Find 以由客户端构造 ExtendedFinding?当然,您可以拥有类似 public 的东西,ExtendedFinding(Finding) { /* copy vars one by one */ }但这远非优雅

4

3 回答 3

1

First your third point, final in no way makes a class immutable - it signifies that the class cannot be inherited from. So you cannot extend a final class.

For your main problem, why don't you cast your POJO to an interface and return a list of that rather than the underlying POJO. You can then make your actual POJO class package private so that the client cannot cast it back:

public static interface Finding {
    //all public getters

    void setUserNote();
}

static final class FindingImpl implements Finding {

    @Override
    public void setUserNote() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}
private final Collection<FindingImpl> findingImpls = new ArrayList<>();

public Collection<Finding> getFindings() {
    final Collection<Finding> findings = new ArrayList<>();
    for (final FindingImpl fi : findingImpls) {
        findings.add(fi);
    }
    return findings;
}
于 2013-03-24T00:58:47.757 回答
1

这不一定是糟糕的设计。不过这听起来并不常见。在设计 API 时牢记 API 的可能用途很重要,但我觉得这有点过分了:

  • 它打破了单一职责原则:该类现在既可以表示用户Findings 也可以作为用户指定数据的容器。
  • 它限制用户使用String笔记而不是任意对象。例如,如果需要,他们将无法使用 Map 或自定义 POJO。(不过,这可以使用泛型轻松解决。)

更好的解决方案可能是在类中定义equalshashCode方法Finding。通过这种方式,这些对象可以用作 a 的键Map,并且用户可以将他们的笔记存储在您的 API 之外。

另一种解决方案可能定义一个新类来表示 aFinding和用户注释对。这比在其他不可变的类中存储笔记具有更清晰的“感觉” Finding,但增加的复杂性可能使其不值得付出努力。哪种解决方案最好取决于具体情况;没有正确或错误的答案。

(顺便说一句,final关键字不会使类不可变。这只是意味着您不能为它定义子类。您可以创建最终的可变类 - 例如StringBuilder

于 2013-03-24T00:58:36.373 回答
0

我很困惑。如果你返回一个发现给我,你认为它是不可变的,那么我一次能够在那个对象中注入一个音符,这有什么意义呢?假设其他人可能会看到相同的发现,不是吗?

这里的正确答案是你应该有另一个类:FindingComment,带有评论者的 id、Finding 的 id 和时间戳。

您将课程扩展到对评论进行评论的直觉肯定是正确的!

于 2013-03-24T02:47:28.103 回答