Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我应该如何组织这些代码(OOP,接口)_Java_Oop_Interface - Fatal编程技术网

Java 我应该如何组织这些代码(OOP,接口)

Java 我应该如何组织这些代码(OOP,接口),java,oop,interface,Java,Oop,Interface,我正在尝试创建一个图表的结构。到目前为止,我正在尝试如何为边创建一些类 图中的边可以是 正规的, 定向、加权(或上述任何一项) 那么你认为组织这个类的最佳方式是什么呢?我在考虑创建一个接口IEdge,然后创建类 public interface IEdge{ } public class DirectedEdge implements IEdge{} public class WeightedEdge implements IEdge{} 但现在我遇到了一个问题,它不是很灵活,如果我想要以下

我正在尝试创建一个图表的结构。到目前为止,我正在尝试如何为边创建一些类

图中的边可以是

正规的, 定向、加权(或上述任何一项)

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

public interface IEdge{
}

public class DirectedEdge implements IEdge{}
public class WeightedEdge implements IEdge{}
但现在我遇到了一个问题,它不是很灵活,如果我想要以下内容呢

public class DirectedWeightedEdge implements IEdge{}

您将如何编写此代码?

在此处使用装饰器模式可能比较合适:


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

为什么要显式创建边?到目前为止,在每个图形实现中,边都隐式地存在于节点对象中。在每个节点中,您都需要一个相邻节点的数组—如果需要对它们进行加权,只需添加一个整数即可

方向也很自然地依此而来(双向图很容易用单向图来表示)。显然,如果图形足够小,也可以将它们保存为邻接矩阵,这对于并行算法来说非常好。。但是如果性能很重要,我们讨论的是完整矩阵无法使用的尺寸

编辑:在评论之后,我想我应该澄清一点:使用一个Edge类来保存关于Edge(颜色、权重)的附加信息是可以的,但我总是将它作为特定节点的一部分使用:例如,类似这样的东西-在C中,我会使用一个struct

class Node {
    List<Edge> children;

    class Edge {
        int weight;
        Color color;
        Node dest;
    }
}
类节点{
列出儿童名单;
阶级边缘{
整数权重;
颜色;
节点dest;
}
}

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

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

然而,权重只是可以栓在现有边缘上的东西,因此装饰图案是最适合它们的

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

这不是面向对象的练习——我的意思是,首先使用逻辑,然后查看模式。有向图和无向图是非常不同的。有向边有起点和终点,无向边只有两个节点。您可以将它们称为开始和结束,以获得一个公共的基础,但没有向边添加方向性这样的东西

同时,边可能有颜色、权重、价格、长度、容量等。是否确实要实现
彩色权重价格边长容量限制ge
?或者你想使用5个装饰器?我希望你不要

我的第一点是,“方向性”并不适合任何模式。您可以使用属性“isDirected”或其他任何东西,并且可能根本不需要它,因为大多数图形不会混合不同类型的边。因此,每个
图形的单个属性应该可以。通常,无向边由一对两个有向边表示


我的第二点是,一般来说,重量之类的东西不应该被强行放在边缘。使用
映射
作为
图形的属性
做得更好。您仍然可以使用像Edge和Node这样的对象,这样可以避免混淆它们(在C中很容易发生这种情况,您可能会使用它们的
id
s),但将它们的属性保留在外部。

一种类型,两种属性

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

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

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)
    }
}
公共类节点{
类邻接yinfo{
节点;
特奇边缘;
公共邻接YInfo(节点,TEdge边){
// ....
}
}
布尔isDiGraph;
列表;
///..构造函数、其他方法
公共TEdge连接到(节点){
TEdge=新TEdge();
邻接yinfo a0=新的邻接yinfo(节点,e);
本调整加(a0);
if(!isDiGraph){
AdjacencyInfo a1=新的AdjacencyInfo(本,e);
节点调整添加(a1);
}
return e;//返回边缘,以便调用方能够设置边缘属性(重量、颜色等)
}
}

这样的方法应该可以很好地解决定向/非定向问题。我不知道使用Java泛型可以完成多少工作,因为除了避免容器中的类型转换之外,Java泛型在其他方面几乎不可用,但是,如果您需要只处理加权边,则可以通过将权重设置为1或任何有意义的设置来避免泛型。

如何使用一个必须显示图形的软件,例如边具有颜色。你能把它也塞进节点吗?当然不是。不,我会使用Edge类,但我永远不会区分定向/无向或其他任何东西。只是一个节点和附加信息(正如我对加权图所说的)——这是一个边实现。你是对的,也许我误解了他对边类的意图。嗯,这是一个有趣的想法,但边总是恰好属于两个节点。因此,在您的实现中,一条边将由两个边对象表示。这可能是有效的,但听起来不太对劲