我该如何组织这个代码(OOP,接口)

时间:2011-02-16 23:02:45

标签: java oop interface

我正在尝试为图表创建结构。到目前为止,我正在努力弥补我应该如何为边创建一些类。

图表中的边缘可以是

正, 指导,加权(或以上任何一种)。

那么你认为组织这个类的最佳方式是什么,我想创建一个接口IEdge,然后创建类

public interface IEdge{
}

public class DirectedEdge implements IEdge{}
public class WeightedEdge implements IEdge{}

但是现在我遇到了一个问题,它不是很灵活,如果我想要以下内容

public class DirectedWeightedEdge implements IEdge{}

你会如何编码?

6 个答案:

答案 0 :(得分:2)

为什么要明确创建边缘?在每个图形实现中,到目前为止,边缘存在于节点对象中。在每个节点中,您需要一组相邻节点 - 如果您需要它们,只需添加一个整数。

方向也很自然地来自(也就是双向图很容易用单向表示)。显然,如果图形足够小,你也可以将它们保存为邻接矩阵 - 这对并行算法来说非常好。但是如果性能很重要,那么我们谈的是完整矩阵不可用的大小。

编辑:评论之后我想我应该澄清一点:使用Edge类来保存关于边缘(颜色,重量)的附加信息很好,但我总是将它用作特定节点的一部分:I.e。像这样的事情 - 在C中我会使用一个结构。

class Node {
    List<Edge> children;

    class Edge {
        int weight;
        Color color;
        Node dest;
    }
}

答案 1 :(得分:2)

这不是OOP练习 - 我的意思是,首先使用逻辑,然后查看模式。有向图和无向图是非常不同的野兽。有向边具有开始和结束,无向有边仅有两个节点。你可以将它们称为开始和结束,以获得一个共同的基础,但是没有定向这样的东西被添加到边缘。

同时,边缘可能有颜色,重量,价格,长度,容量等。您真的想要实施ColoredWeightedPricedHavingLenghtCapacityLimitedEdge吗?或者你想使用5个装饰器?我希望你不要。

我的第一点是“指向性”并不适合任何模式。您可以使用属性“isDirected”或其他任何东西,也许您根本不需要它,因为大多数图形不会混合不同类型的边缘。因此每个Graph应该有一个属性。很多时候,一个无向边缘由一对两个有向的边缘代表。

我的第二点是,重量之类的东西一般不应该强行放在边缘。使用Map<IEdge, Double>作为Graph的属性可以做得更好。你仍然可以使用像Edge和Node这样的对象,这会阻止它们混淆(在你可能使用它们id的情况下很容易发生的事情),但是保持它们的属性是外部的。

答案 2 :(得分:1)

我使用了继承和前面提到的装饰模式的混合。

有向和无向边的行为完全不同,它们是强制性的并且是互斥的。因此,它们应该是Edge接口的唯一两个实现。

然而,权重只是你可以在现有边缘上固定的东西,因此装饰器模式对他们来说是最合适的。

但是要暂时回到原点,取决于共享代码定向和无向边的数量,可能Edge抽象类比接口更好。当然,“正确”的解决方案是同时拥有:一个接口,由一个抽象类实现,由两个具体类扩展。但在这种情况下,这听起来像过度工程。

答案 3 :(得分:0)

在这里使用装饰器模式可能是合适的: http://en.wikipedia.org/wiki/Decorator_pattern

基本上,您将拥有一个实现IEdge的基类,以及同时实现IEdge接口的DirectedEdgeDecorator和WeightedEdgeDecorator类。 * Decorator类将“包装”基本边缘类并为其添加附加功能。使用此模式,您可以在IEdge上堆叠多个装饰器,一个在另一个上,以不同的方式修改其行为。

答案 4 :(得分:0)

您可以将边缘信息与邻接信息分开。这意味着您不会复制边数据,而是将它们存储在邻接列表中。

public class Node<TEdge> {
    class AdjacencyInfo {
       Node<TEdge> node;
       TEdge edge;

       public AdjacencyInfo(Node<TEdge> node, TEdge edge) {
          // ....
       }
    }

    bool isDiGraph; 
    List<AdjacencyInfo> adj;
    ///.... constructor, other methods

    public TEdge ConnectTo(Node<TEdge> node) {
       TEdge e = new TEdge();
       AdjacencyInfo a0 = new AdjacencyInfo(node, e);
       this.adj.Add(a0);
       if (!isDiGraph) {
           AdjacencyInfo a1 = new AdjacencyInfo(this, e);
           node.adj.Add(a1);
       }
       return e; // return the edge so caller is able to set edge properties (weight, color, etc)
    }
}

这样的事情应该有效并且能够清楚地解决定向/非定向问题。我不知道使用Java泛型可以实现多少这一点,因为除了避免容器中的类型转换之外,它们几乎不能用于其他事情,但是如果你需要只能处理加权边缘,那么你可以避免泛型将重量设置为1或任何有意义的。

答案 5 :(得分:-2)

一种类型,有两个属性

type Edge
    boolean directed = false;
    number  weight = 1;