假设我有一个对象类,如下所示:
public class MyObject() {
// ...
public double distanceTo(MyObject other) {
// **edit: check if desired distance is contained in distanceMatrix**
// **of the collection in which this object is contained**
// **if not:** some time-consuming calculation
}
}
我还有一个包含此类对象的自定义集合:
public class MyObjectCollection() {
private List<MyObject> objects;
private double[][] distanceMatrix;
// ...
public void add(MyObject obj) {
this.objects.add(obj);
}
public void calcDistanceMatrix() {
for (int i = 0; i < objects.size(); i++) {
for (int j = 0; j < objects.size(); j++) {
this.distanceMatrix[i][j] = objects.get(i).distanceTo(objects.get(j));
}
}
}
}
所以这个想法是只计算一次所有MyObject
之间的所有距离,并将它们存储在一个矩阵中。现在,当有人在MyObject
上调用distanceTo
时,它应该使用缓存的值而不是再次计算它。
但是,要使其正常工作,每个MyObject
都必须知道它包含的集合 - 或者知道吗?由于分离,我想避免这种情况。
(我知道我可以将从MyObject
obj1
到其他MyObject
的所有距离存储为obj1
中的字段,但我也不想这样做。例如,这意味着为每个MyObject
重建MyObjectCollection
结构(出于其他原因无论如何我都需要)。
我认为您需要做两件事才能将耗时的计算和依赖性与集合分开:
1)在MyObject上,将获取缓存距离的逻辑和进行实际计算的逻辑分成不同的方法。
2) 按照策略模式将获取两个对象之间距离的逻辑移动到接口中:
以下是显示它的修改代码:
public interface DistanceCalc{
public double distanceTo(MyObject from, MyObject to);
}
public class MyObject{
private DistanceCalc distanceCalc = null;
public void setDistanceCalc(DistanceCalc distanceCalc) {
this.distanceCalc = distanceCalc;
}
public double distanceTo(MyObject other) {
return distanceCalc.distanceTo(this, other);
}
public double calculateDistance(MyObject to) {
return 5.0; //this is where time consuming calculation happens
}
}
public class MyObjectCollection implements DistanceCalc{
private List<MyObject> objects;
private double[][] distanceMatrix;
public void add(MyObject obj) {
this.objects.add(obj);
obj.setDistanceCalc(this);
}
@Override
public double distanceTo(MyObject from, MyObject to) {
if (distanceMatrix == null) calcDistanceMatrix();
return distanceMatrix[ objects.indexOf(from) ][ objects.indexOf(to) ];
}
public void calcDistanceMatrix() {
for (int i = 0; i < objects.size(); i++) {
for (int j = 0; j < objects.size(); j++) {
this.distanceMatrix[i][j] = objects.get(i).calculateDistance( objects.get(j) );
}
}
}
}