我认为您的矩阵概念不是实现目标的好方法。你最终会得到一个包含所有可能性的巨大矩阵。显然,从矩阵中提取您希望的信息将相当容易,但从长远来看,随着更多CellObject 子类的添加,维护它可能会被证明是一种痛苦的体验。这同样适用于您同事建议的 n + 1 种方法。
在这两种情况下,每次添加CellObject 的子类时,您都必须转到保存矩阵的类,为每个现有行创建一个新行和一个新列,并手动指定是否这个新类可以堆叠或不堆叠在类 x 上,或者为每个现有类添加一个新方法 canStackOnNewClassX ()。在我看来,这两种解决方案都容易出错(您可能很容易忘记更新矩阵,或者输入错误的信息,因为代码可能不容易阅读),有更优雅的方法来处理此类问题。
您可以做的一件事是在您的 CellObject 超类中拥有一个地图,该地图将保存您的“可堆叠性”信息,并提供填充此地图的方法以及检索 A 类的成员是否可以堆叠在B 类的成员。像这样:
public abstract class CellObject
{
private static Map<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> fullStackabilityMap =
new HashMap<Class<? extends CellObject>, Map<Class<? extends CellObject>, Boolean>> ();
protected static void addStackableOnObjectInformation (Class<? extends CellObject> baseObjectClass, Class<? extends CellObject> objectToStack, boolean canStackOnObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = fullStackabilityMap.get (baseObjectClass);
if (stackableMapForObject == null)
{
stackableMapForObject = new HashMap<Class<? extends CellObject>, Boolean> ();
fullStackabilityMap.put (baseObjectClass, stackableMapForObject);
}
stackableMapForObject.put (objectToStack, canStackOnObject);
}
protected boolean isStackableOnObject (CellObject baseObject)
{
Map<Class<? extends CellObject>, Boolean> stackableMapForObject = CellObject.fullStackabilityMap.get (baseObject.getClass ());
if (stackableMapForObject == null)
{
return false;
}
Boolean canStackOnObject = stackableMapForObject.get (this.getClass ());
return canStackOnObject != null ? canStackOnObject : false; //Assume that the object cannot be stacked if it was not specified
}
}
public class CellObjectA extends CellObject
{
}
public class CellObjectB extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectB.class, CellObjectA.class, true);
}
}
public class CellObjectC extends CellObject
{
static
{
addStackableOnObjectInformation (CellObjectC.class, CellObjectA.class, true);
addStackableOnObjectInformation (CellObjectC.class, CellObjectB.class, true);
}
}
在CellObject 中创建fullStackabilityMap 似乎很复杂,因为Java 在Java 6 中缺少菱形运算符,但是如果您编写一个创建地图的实用方法或使用Guava,则可以简化它。
因此,在此示例中,CellObjectC 实例不能堆叠在各种对象上; CellObjectB 实例只能堆叠在 CellObjectC 对象上,CellObjectA 可以堆叠在 CellObjectB 或 CellObjectC 对象上。
每次添加新类时,您唯一要做的工作就是更新现有类的静态初始化程序,以确保考虑到这个新类。这种解决方案的优点是:
- 您只需要指定哪种对象可以堆叠在哪种对象上。无需完全初始化具有所有可能性的矩阵。
- 您可以直接询问对象是否可以堆叠在任何类型的对象上,而不必静态轮询外部类,这对我来说更易于维护,并且生成更简洁的代码。
- 您不必维护 n+1 个方法,这些方法会告诉您对象 A 可以堆叠在对象 B 上,如果您最终得到大量
CellObject 子类,那将是一场彻头彻尾的噩梦。