5

我正在尝试在 Java 中创建一个应用程序,该应用程序允许从小种子图生成大的出处图,但我在找出设计类的最佳方法时遇到了一些麻烦。

首先,Provenance 本质上具有图结构、节点和边。我创建了一个 Java 库,它充当出处数据模型到 Java 对象的映射。这允许我从 Provenance 模型中抽象出我的应用程序特定信息。

我的类结构看起来有点像这样:

  • 图(包含节点集和边集)
  • 抽象节点(现在只是一个字符串名称)
    • 代理人
    • 活动
    • 实体
    • Node的其他子类
  • 抽象边缘
    • 一代
    • 协会
    • Edge 的其他子类

现在,我想做的是在充当乘数/饱和度级别的节点和边上提供权重。有几种方法可以使用该库来实现这一目标,但我不清楚从开发和可维护性的角度来看什么是最好的。

首先,我使用一些简单的方法定义了一个 Weighable 接口,例如获取和设置最小和最大权重。

现在,我可以扩展每个子类节点,例如

class WeighableAgent extends Agent implements Weighable

但这需要为每种类型的可用节点提供扩展类,并要求我在每个级别实现 Weighable 接口。

或者,我可以提供一个 mixin,但它仍然依赖于我在每个子类中实现相同的功能。

或者,我可以有一个基于 Agent 的类,但这仍然需要我在每个组合类中实现 Weighable。

或者,我可以只在 Node 类上作曲,例如

class WeighableNode implements Weighable {

    private Node node;

    public WeighableNode(Node node) {
        this.node = node;
    }

    etc etc...

这将允许我只在一个地方实现 Weighable。但是,然后我从使用 WeighableNode 的任何内容中丢失了有关具体类类型的一些重要信息,而我看到的唯一解决方法是提供一个方法:

Node getNode();

由于得墨忒耳定律,我很担心。此外,这个 WeighableNode 将由 PresentationNode 组成,以帮助 Swing,这意味着我最终会链接调用,例如:

presentationNode.getWeighableNode().getNode() instanceof Agent

这似乎很不愉快。

我刚刚想到的一个最终解决方案是如上所述在 Node 上进行组合,然后使用 WeighableAgent 等扩展 WeighableNode。这意味着我不需要每次都重新实现 Weighable,如果我知道我有

instanceof WeighableAgent

那么被包装的节点就是一个代理。

我很欣赏这很长,但我希望有经验的开发人员能很快看到正确的设计实践。

4

1 回答 1

2

太糟糕了,Java 既没有真正的 mixin,也没有多重继承……</p>

通用包装器

我想我会WeighableNode<NodeType extends Node>用作通用包装器类型。这样,所有需要特定类型节点的地方都可以清楚地说明这一事实。它的getNode方法可以返回正确的类。而且你不会到处都有太多的课程。

转换成语

即使您不使用上述方法,以下成语也可能很有趣:

class Node {
    public T asNode(Class<T extends Node> clazz) {
        return clazz.cast(this);
    }
}

class NodeWrapper<N extends Node> {
    private N realNode;
    public T asNode(Class<T extends Node> clazz) {
        try {
            return super.asNode(clazz);
        }
        catch (ClassCastException e) {
            return realNode.asNode(clazz);
        }
    }
}

如果您愿意,您可以将上述内容更改为返回null而不是抛出异常。这个想法是调用代码不必担心如何将您的节点转换为各种类型。你会例如简单地写

presentationNode.getNode(Agent.class)

这将实现与接口分开,让您在以后有需要时可以自由地进行更改。基本Node实现将知道如何转换自己,照顾派生类。将NodeWrapper使用组合添加转换。您可以将其用作WeighableNode和您的presentationNode.

胖接口

您可以自己实现称重的东西Node,并WeighedNode仅用作标记接口,或者根本不使用。不是最好的解决方案,但会帮助减少类的数量,并且除了额外数据消耗的内存位之外不应该造成任何真正的伤害。到目前为止,其他方案所需的间接级别可能会超过内存需求。

于 2012-07-18T15:59:44.053 回答