Java 如何在删除时设计多对多关系?
我正在创建一个带有两个对象的Java 如何在删除时设计多对多关系?,java,oop,gwt,many-to-many,java-canvas,Java,Oop,Gwt,Many To Many,Java Canvas,我正在创建一个带有两个对象的画布图形:矩形,以及连接矩形的线条。每一行都应该知道它所连接的2个矩形。 每个矩形可以有多条线将其连接到其他矩形s class Rectangle { List<Line> connections; void setConnection(Line line) { connections.add(line); } } class Line { Rectangle from, to; public L
画布图形:矩形,以及连接矩形的线条。每一行都应该知道它所连接的2个矩形。
每个矩形
可以有多条线将其连接到其他矩形
s
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);
}
}
类矩形{
列出连接;
无效设置连接(线路){
连接。添加(行);
}
}
班级线{
矩形从,到;
公用线(矩形从、矩形到){
this.from=from;
这个;
from.setConnection(this);
to.setConnection(本);
}
}
我觉得这可能不是一个好的设计,因为当我删除行
时,我还必须从它连接的矩形
中的连接列表中删除行
当我删除一个矩形
时,我还必须删除连接到该矩形的行
,因为它们不应该存在。因此,我必须遍历可删除的矩形
的所有连接
,对于每个连接
,从
/到
矩形
,然后再次获取连接
列表并删除行
引用
我的问题不是写代码(我已经让它工作了),但在我看来,我做了很多来回的引用
这能做得更好吗?不知何故:如果删除了一个矩形,那么线的所有深连接都会自动删除/失效?类似于Hibernate的多对多级联?我不能只使用Hibernate,因为这应该是一个客户端应用程序,没有数据库。基本上你是在构建图形。需要将边与顶点分开
让我们先创建一些接口来分离一些关注点:
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);
}
}
类画布{
私有连接管理器ConnectionManager=新连接管理器();
私有集形状=新HashSet();
公共画布(){
}
公共空间移除形状(形状){
如果(!shapes.remove(shape))
返回;
if(shape.getClass().isAnnotationPresent(CascadeDeleteConnectedShapes.class)){
形状(形状);
}
if(ShapeConnection的形状实例){
connectionManager.remove((ShapeConnection)形状);
}
}
私有空心形状(形状形状){
List connections=connectionManager.getConnections(shape);
for(ShapeConnection连接:连接){
if(形状的连接实例){
此。移除形状((形状)连接);
}否则{
connectionManager.移除(连接);
}
}
}
公共空心形状(形状){
if(shapes.contains(shape))
返回;
if(ShapeConnection的形状实例){
addShapeConnection((ShapeConnection)形状);
}
形状。添加(形状);
}
私有void addShapeConnection(ShapeConnection ShapeConnection){
对于(形状:shapeConnection.getConnectedShapes()){
如果(!shapes.contains(shape))
抛出新错误(“无法连接未知形状”);
}
connectionManager.add(shapeConnection);
}
}
形状可以同时是形状连接。将几个矩形添加到画布后,可以添加线来连接它们。由于设计中的一条线被识别为ShapeConnection
,因此涉及该线的任何操作都将调用Canvas
以让ConnectionManager
处理图形。在这种设计中,行
是不可变的,这一点很重要
级联是通过删除带注释的形状触发的。您需要小心地管理这些级联:如果在过程中的某个地方发生异常,您将得到一个不完整的图
这段代码只是给你一个想法。另外,我将把连接管理器的实现留给您想象。其中一条评论提到了番石榴。A本可以正好达到你的目的,可惜他们还没有发布。无论如何,我肯定会考虑让现有库处理ConnectionManager
的细节;很多都是适合你需要的
请注意,此设计中不存在任何连接。为了删除深层连接,需要以某种方式对其进行评估。您可以像以前一样在删除时进行检查,也可以让它在访问时进行检查(将指针设置为null,然后,当有人试图访问它并看到null时,它会删除该行)。这样可以节省初始删除的时间,但每次访问都会增加一点开销,如果您实际上不访问它们,则会使用更多内存。与垃圾收集()问题非常类似,您可以使用映射
,其键类型为矩形
,值为行
对象的集合(或番石榴多映射
)。如果有很多矩形和直线,这可以显著提高性能。当然,您可以从矩形
类中删除列表
。实际上,我想我可能会引入一个类来管理“连接点”,并包含矩形/直线的映射。(顺便说一句,我认为在使用GWT编程时,最好使用一个具体的类,比如ArrayList
,而不是抽象类List