设计问题:如何最好地使用构图



我正在做一个项目,对它的设计有一些疑问。我如何才能最好地设计以下问题(在JAVA中(:

A类具有以下属性:

  • 像素的哈希集,其中每个像素具有x、y坐标,值v在0-1之间
  • B类的实例

B类具有以下功能:

  • 一个获取Pixel并返回其左邻居的函数

当我在类A中时,我想在A中的每个像素上使用B.函数,并仅当它还没有存在时将其添加到HashSet中。问题是,我不想将HashSet发送到函数,如果函数可能已经存在,那么从函数返回Pixel的新实例有多糟糕(该函数将在许多像素上运行,并将创建许多未使用的Pixel实例(。

我还有什么其他选择?

由于使用Set<Pixel>,因此必须创建新的Pixel实例来检查它是否存在于集合中。

如果集合在调用B.function方法后包含N元素,则将创建额外的NPixel节点。如果所有元素都是新的,您只需将它们添加到集合中,在其他情况下Garbage Collection需要扫描它们。缺点之一是我们需要创建m(其中m <= N-集合中已经存在的Pixel-的数量(,然后我们需要通过GC来收集它们。m/N比率有多大取决于你的算法和你实际在做什么。

让我们计算集合中N = 1_000_000像素需要消耗多少内存。我们知道int4 bytesdouble8 bytes,让我们为对象添加额外的8 bytes,为引用添加8 bytes。它为Pixel对象的每个实例提供了32 bytes。我们需要创建N对象,它给出32MB。让我们假设我们的比率是50%,所以我们分配的16MB只是为了检查它是否不需要。

如果这是一个你无法支付的成本,你需要开发一种算法,允许你按照left-to-right的顺序迭代Set<Pixel>。因此,Pixel的左相邻XX之前。

假设CCD_ 31的CCD_ 32的左相邻像素是像素CCD_。CCD_ 34B(0, y)没有左邻居。您需要使用TreeSet并在Pixel类中实现Comparable<Pixel>接口。简单的实现可能是这样的:

@Override
public int compareTo(Pixel o) {
return this.y == o.y ? this.x - o.x : this.y - o.y;
}

这允许您按从左到右的顺序迭代集合:(0, 0), (1, 0), ...., (x - 1, y), (x, y), (x + 1, y), ... , (maxX, maxY)。因此,当您迭代它时,您可以检查前一个元素是否是当前Pixel的左邻居。示例实现如下所示:

void addNeighboursIfNeeded() {
Set<Pixel> neighbours = new HashSet<>(pixels.size());
Pixel last = null;
for (Pixel p : pixels) {
if (p.getX() == 0 || p.isLeftNeighbour(last)) {
// a left border pixel
// or last checked element is a left neighbour of current pixel.
last = p;
continue;
}
// last element was not our left-neighbour so we need to call b method
Pixel left = b.getLeft(p);
neighbours.add(left);
last = p;
}
// add all new neigbours
pixels.addAll(neighbours);
}

这应该允许您保存分配给重复Pixel对象的内存。

我可以在这里看到一些关于面向对象编程的问题。

  1. 封装冲突:当您从对A的数据进行操作的A调用B的函数时(通过不发送HashMap来避免(,它违反了封装(如果有原因,它是可以接受的(。是否可以将该函数(在A的HashSet上操作(移动到A?这将保护A的状态不被暴露
  2. 类的扩散:可能会有大量点类型的对象。您可以考虑使用Flyweight GOF设计模式,它将具体化每个点的状态,并使其可重复使用。并且将显著减少数量
  3. 将大量的Points集合传递给B中的方法:如果可以将方法从B转移到A,则此点将得到解决。无论如何,java将通过引用传递此集合。但在这种情况下,它对来自外部类的修改是开放的(需要注意这一方面(
  4. 类型Point的抽象:如果类Point只有状态而没有行为,则会导致违反封装。你能把getNeighbour中的方法移到Point吗?因为它将使Point不可变(这是必不可少的(。当然,实际的算法可以委托给另一个类(如果它的职责独立变化,并且有算法的层次结构,请在这里考虑GOF策略模式(
  5. 集合中点的唯一性:您的集合将注意适当的Hash和类Point的逻辑相等性

相关内容

最新更新