我怎样才能最好地让一个班级为另一个班级举办一些活动?

时间:2014-04-24 00:46:32

标签: java design-patterns

我遇到了一些尴尬的情况,从某种意义上说,它们彼此是双重的,并且想知道是否有人对如何干净地处理它们有任何想法。

外部初始化

class Human {
   Collection <Human> nextDoorNeighbors;
}

class Neighborhood {
   Collection <Human> humans;
   Neighborhood() {
     // Make humans
     // Then, let them all know who their neighbors are.
   }
}

这很尴尬,因为人类(在这种情况下)一旦设置(他们实际上只写一次)就不必改变他们的隔壁邻居,但这种设置不可能在Human构造函数中完成,因为当构造人类时,需要放入nextDoorNeighbors集合中的邻居不会存在

为另一个人拿着东西

假设我希望能够将人类存储在基于树的地图中。要做到这一点,人类必须拥有可比较的ID,即使这在人类的概念上没有逻辑意义。 Human构造此ID,但它从不使用它。只有地图使用它(甚至应该使用它)。

3 个答案:

答案 0 :(得分:1)

在第一种情况下,尴尬可能表明邻居不应该是人类的财产。也许Neighborhood对象应该是Human的属性,并且像human.getNeighbours()这样的方法可以用于在需要时获取实际的邻居。然后,具有邻居属性成为getNeighbours()方法的私有性能问题。

在第二种情况下,如果人类本身具有不可构建性,那么基于树的地图如何提供​​结构?如果ID与人类无关,那么地图是什么?通常,ID是相关的,并且由具有它的类使用以确保它是唯一可识别的,但如果真的不需要,则可以使用单独的类(如HumanKey)将Human包装为地图。

答案 1 :(得分:0)

我真的不明白你的问题是什么......因为它不明确..

但是对于id,你可以在人类中拥有一个静态变量,你将在人类构造函数中增加,另一个变量将包含id

就像这样

class Human 
{
   private static int humansCounter=0;
   final public int id;

   public Human()
   {
      id=humansCounter++;
   }

}

答案 2 :(得分:0)

如果对象本身需要了解网络,我认为这种方法相当干净。请注意,如果您同时实例化实例(因为每个线程都有自己的static字段副本),此方法将不起作用。

class Foo {
    // instance fields

    public Foo(/* constructor args */) {
        // set instance up
        network(this);
    }

    public boolean isNeighbor(Foo that) {
        return areNeighbors(this, that);
    }

    // static field for tracking edges between neighbors, maybe a
    private static Map<Foo, List<Foo>> neighborhood = new HashMap<>();

    private static void network(Foo me) {
        myNeighbors = new ArrayList<>();
        for (Map.Entry<Foo, List<Foo>> x : neighborhood.entrySet()) {
            Foo n = x.getKey();
            if (/* use me and n's fields to determine whether they are neighbors */) {
                myNeighbors.add(n);
                x.getValue().add(me);
            }
        }
        neighborhood.put(me, myNeighbors);
    }

    public static boolean areNeighbors(Foo a, Foo b) {
        return neighborhood.get(a).contains(b);
    }
}

这种方法使得每个实例都可以在不事先知道邻居的情况下确定其邻居,而无需使用外部类。如果无法从内部状态推断出实例的邻居,则可以将此方法与为每个实例生成唯一ID(哈希?)的方法结合使用:

class Bar {
    // instance fields

    public Bar(/* constructor args */, int... neighborIndices) {
        // set instance up
        network(this, neighborIndices);
    }

    @Override
    public int hashCode() {
        return /* a unique value based upon this object's state */;
    }

    public boolean isNeighbor(Bar that) {
        return areNeighbors(this, that);
    }

    private static Map<Integer, Bar> lookup = new HashMap<>();
    private static Map<Bar, List<Integer>> neighbors = new HashMap<>();

    private static void network(Bar me, int[] neighbors) {
        lookup.put(me.hashCode(), me);

        List<Integer> neighborList = new ArrayList<>();
        for (int i : neighbors) {
            neighborList.add(i);
        }
        neighbors.put(me, neighborList);
    }

    public static boolean areNeighbors(Bar a, Bar b) {
        return neighbors.get(a).contains(b.hashCode());
    }
}

当然,如果邻居关系不是关联的,那么将第一个例子修改为有向图是很容易的。