2

canvas2つのオブジェクトで図面を作成しています: Rectangles、およびLines長方形を接続しています。各回線は、Rectangle接続する2秒を認識している必要があります。すべてRectangleが他のものに接続する複数の線を持つことができますRectangle

class Rectangle {
    List<Line> connections;
    void setConnection(Line line) {
        connections.add(line);
    }
}

class Line {
    Rectangle from, to;

    public Line(Rectangle from, Rectangle to) {
        this.from = from;
        this.to = to;

        from.setConnection(this);
        to.setConnection(this);
    }
}

を削除すると、接続する接続リストからLineも削除する必要があるため、これは適切な設計ではない可能性があると思います。LineRectangle

を削除するときは、長方形に接続されているsRectangleも削除するLine必要があります。これは、がないと存在してはならないためです。connectionsしたがって、削除可能なすべてのを反復処理する必要がRectangleあり、それぞれに対して/をconnection取得し、そこで再びリストを取得して参照を削除します。fromto rectangleconnectionLine

私の問題はそのコードを書くことではありません(私はすでにそれを機能させています)が、私は何度も何度も参照を行っているようです。

これはもっとうまくできるでしょうか?どういうわけか:長方形が削除されると、線からのすべての深い接続が自動的に削除/無効化されますか?Hibernateの多対多のカスケードに似たものはありますか?これはデータベースなしのクライアント側アプリであると想定されているため、Hibernateを使用することはできません。

4

1 に答える 1

1

基本的に、グラフを作成しています。頂点からエッジを分離する必要があります。

いくつかの懸念を分離するいくつかのインターフェースを作成することから始めましょう:

interface Shape {
}

interface ShapeConnection {
    Shape[] getConnectedShapes();
}

次に、接続された形状をカスケード削除する必要がある形状をマークする注釈を導入しましょう。

@interface CascadeDeleteConnectedShapes {
}

長方形と線は次のように定義できます。

@CascadeDeleteConnectedShapes
class Rectangle implements Shape {

}

class Line implements Shape, ShapeConnection {
    Rectangle from, to;

    public Line(Rectangle from, Rectangle to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public Shape[] getConnectedShapes() {
        return new Shape[] { from, to };
    }
}

最後に、すべてをまとめることができる場所が必要になります。

class Canvas {
    private ConnectionManager connectionManager = new ConnectionManager();

    private Set<Shape> shapes = new HashSet<Shape>();

    public Canvas() {
    }

    public void removeShape(Shape shape) {
        if (!shapes.remove(shape))
            return; 

        if (shape.getClass().isAnnotationPresent(CascadeDeleteConnectedShapes.class)) {
            cascadeDeleteShape(shape);
        }

        if (shape instanceof ShapeConnection) {
            connectionManager.remove((ShapeConnection) shape);
        }
    }

    private void cascadeDeleteShape(Shape shape) {
        List<ShapeConnection> connections = connectionManager.getConnections(shape);
        for (ShapeConnection connection : connections) {
            if (connection instanceof Shape) {
                this.removeShape((Shape) connection);
            } else {
                connectionManager.remove(connection);
            }
        }
    }

    public void addShape(Shape shape) {
        if (shapes.contains(shape))
            return;

        if (shape instanceof ShapeConnection) {
            addShapeConnection((ShapeConnection) shape);
        }

        shapes.add(shape);
    }

    private void addShapeConnection(ShapeConnection shapeConnection) {
        for (Shape shape : shapeConnection.getConnectedShapes()) {
            if (!shapes.contains(shape))
                throw new Error("cannot connect unknown shapes");
        }
        connectionManager.add(shapeConnection);
    }
}

形状は、同時に形状接続にすることができます。キャンバスにいくつかの長方形を追加したら、それらを接続するための線を追加できます。デザイン内の線は、線を含むすべての操作として認識されるため、をShapeConnection呼び出してグラフを処理します。この設計では、不変であることが重要です。CanvasConnectionManagerLine

カスケードは、注釈付きの形状の削除によってトリガーされます。これらのカスケードを注意深く管理する必要があります。途中で例外が発生した場合、不完全なグラフが残ります。

このコードはあなたにアイデアを与えるためだけに役立ちます。また、接続マネージャーの実装はあなたの想像に任せています。グアバはコメントの1つで言及されています。BiMultiMapはあなたの目的を正しく果たしていただろうが、彼らがまだそれをリリースしていないのは残念だ。いずれにせよ、私は確かに、の詳細をConnectionManager既存のライブラリで処理できるようにすることを検討します。多くはあなたのニーズに合うように書かれています。

この設計には循環依存関係がないことに注意してください。

于 2013-03-27T04:15:39.257 に答える