通过java中的继承,为不同的实现重用algo逻辑

时间:2016-11-14 05:40:40

标签: java algorithm inheritance data-structures

我正在尝试在java中实现Graph数据结构。 以下是课程:

interface Graph<N,E> {
    addNode(N nodeData);
    createEdge(N src, N dest, E edgeData);
    //and many more api methods
}

class GenericGraph<N,E> implements Graph<N,E> {

    Set<Node<N,E>> vertices;

    static class Node<N,E> {
        private N node;
        private Set<Edge<N, E>> adjacencyList;

        // getters and setters
    }

    static class Edge<N, E> {

        private E edgeData;
        private Node<N, E> src;
        private Node<N, E> dest;

        // getters and setters
    }

    //******** API methods implementation*********

    Node<N, E> findNode(N nodeData) {
        Node<N, E> node = new Node<>(nodeData);
        if (vertices.contains(node)) {
            for (Node<N, E> tempNode : vertices) {
                if (Objects.equals(tempNode, node)) {
                    node = tempNode;
                    return node;
                }
            }
        }
        return null;
    }

    Node<N, E> createNode(N nodeData) {
        Node<N, E> node = findNode(nodeData);
        if (node == null) {
            node = new Node<>(nodeData);
            vertices.add(node);
        }
        return node;
    }

    @Override
    public void addNode(N nodeData) {
        createNode(nodeData);
    }

    // other api methods
}

这里我创建了两个嵌套类:Node和Edge

一个图形对象可以有许多节点。

一个节点对象可以有一个相邻顶点的列表。

相邻顶点被视为Edge,其中包含

->src node
->dest node
->edge relation bw the two

GenericGraph api方法使用Node和Edge类来实现。

直到现在一切正常。

现在我想创建一些其他类比GenericGraph更多的功能,比如BfsGraph,DfsGraph等。

BFS算法需要为其节点提供3个额外参数:

->color 
->parent
->distance

我正在考虑像这样创建BfsGraph:

class BfsGraph<N,E> extends GenericGraph<N,E> {

    //access public,protected and default methods of GenericGraph

    private enum NodeColor {
        WHITE, GRAY, BLACK;
    }

    static class BfsNode<N,E> extends GenericGraph.Node<N,E> {
        private NodeColor color = NodeColor.WHITE;
        private Integer distance = Integer.MAX_VALUE;
        private Node<N, E> parent;

        BfsNode(N node) {
            super(node);
        }
    }
}

这个设计的问题是,我必须从GenericGraph复制每个方法并根据自己的需要在BfsGraph中重新实现它(Node将更改为BfsNode)。

将来如果我想进行其他实现,那么我再次需要复制和修改所有方法。

必须重复使用GenericGraph编写的算法/逻辑,而不是重写。

请为我推荐一个新的解决方案或任何修改。

1 个答案:

答案 0 :(得分:1)

从您的描述中,听起来子类需要能够控制两件事:

  • 创建的Node实例必须是Node子类型的实例。
    • 这可以通过在protected中创建一个名为GenericGraph的{​​{1}}方法来处理,该方法只是实例化createNode。然后Node可以在需要GenericGraph实例时调用该方法;和子类可以覆盖该方法,以提供Node的正确子类型。
    • 我注意到你已经有了Node方法,但除了创建节点之外还有其他逻辑。您应该将该方法重命名为能够捕获其全部用途的方法。
  • 需要将createNode方法声明为返回findNode的相应子类型。

    • 这可以通过让子类覆盖Node来处理,但是覆盖只需委托给超类并执行适当的强制转换,如下所示:

      findNode
    • 如果你有很多像这样的方法,那么你可能会考虑让BsfNode<N, E> findNode(N nodeData) { return (BsfNode<N, E>) super.findNode(nodeData); } 实际上把它的节点类型作为一个类型参数,这样就可以通过泛型的魔力来处理,而不是要求显式覆盖。但这听起来并不像你认为这种方法值得的那样。