不确定应用程序的设计方法

Wil*_*tin 5 java

我正在尝试用Java创建一个应用程序,它允许从小种子图生成大型的Provenance图,但是我在设计我的类的最佳方法时遇到了一些麻烦.

首先,Provenance基本上有一个图形结构,节点和边缘.我创建了一个Java库,它充当了Provenance Data Model到Java Objects的映射.这允许我从Provenance模型中抽象出我的应用程序特定信息.

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

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

现在,我想要做的是在节点和边缘上提供加权,作为乘数/饱和度.我可以通过两种方式使用该库来实现这一目标,但我不清楚从开发和可维护性的角度来看哪些是最好的.

首先,我使用一些简单的方法定义了一个Weighable接口,例如get和set最小和最大权重.

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

class WeighableAgent extends Agent implements Weighable
Run Code Online (Sandbox Code Playgroud)

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

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

或者,我可以有一个在Agent上编写的类,但是仍然需要我在每个组合类中实现Weighable.

或者,我可以仅仅在Node类上编写,例如

class WeighableNode implements Weighable {

    private Node node;

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

    etc etc...
Run Code Online (Sandbox Code Playgroud)

这将允许我只在一个地方实现Weighable.但是,我从使用WeighableNode的任何东西中丢失了一些关于具体类类型的重要信息,我看到的唯一方法就是提供一个方法:

Node getNode();
Run Code Online (Sandbox Code Playgroud)

由于德米特定律,我对此感到担忧.此外,这个WeighableNode将由PresentationNode组成,以帮助Swing,这意味着我最终将链接调用,例如:

presentationNode.getWeighableNode().getNode() instanceof Agent
Run Code Online (Sandbox Code Playgroud)

这看起来很不愉快.

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

instanceof WeighableAgent
Run Code Online (Sandbox Code Playgroud)

然后包装的节点是一个代理.

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

MvG*_*MvG 2

可惜 Java 既没有真正的 mixins,也没有多重继承\xe2\x80\xa6

\n\n

通用包装器

\n\n

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

\n\n

转换习语

\n\n

即使您不使用上述方法,以下习惯用法也可能会很有趣:

\n\n
class Node {\n    public T asNode(Class<T extends Node> clazz) {\n        return clazz.cast(this);\n    }\n}\n\nclass NodeWrapper<N extends Node> {\n    private N realNode;\n    public T asNode(Class<T extends Node> clazz) {\n        try {\n            return super.asNode(clazz);\n        }\n        catch (ClassCastException e) {\n            return realNode.asNode(clazz);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
presentationNode.getNode(Agent.class)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将实现与接口分开,让您可以在以后需要时自由地进行更改。基本Node实现将知道如何转换自身,并处理派生类。将NodeWrapper使用组合添加转换。WeighableNode您可以使用它作为您的基类presentationNode

\n\n

胖接口

\n\n

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

\n