对于“伪类型反模式”,有没有理由?

时间:2009-08-07 07:46:35

标签: java typedef anti-patterns

我有一个相对复杂的泛型类型(比如Map<Long,Map<Integer,String>>)我在一个类中内部使用。 (没有外部可见性;它只是一个实现细节。)我想在typedef中隐藏它,但Java没有这样的功能。

昨天我重新发现了以下习语,并且感到很失望,因为它是considered an anti-pattern


class MyClass
{
  /* "Pseudo typedef" */
  private static class FooBarMap extends HashMap<Long,Map<Integer,String>> { };

  FooBarMap[] maps;

  public FooBarMap getMapForType(int type)
  {
    // Actual code might be more complicated than this
    return maps[type];
  }

  public String getDescription(int type, long fooId, int barId)
  {
    FooBarMap map = getMapForType(type);
    return map.get(fooId).get(barId);
  }

  /* rest of code */

}

当隐藏类型并且不构成库API的一部分时(在我看来,Goetz对使用它的主要反对意见)是否有任何理由呢?

6 个答案:

答案 0 :(得分:10)

IMO,Java反模式的问题在于它们鼓励黑白思维。

实际上,大多数反模式都是微妙的。例如,链接的文章解释了伪typedef如何导致API类型签名过于严格,与特定的实现决策,病毒等相关联。但这完全是在公共API的背景下。如果你将伪typedef保留在公共API之外(即将它们限制在一个类,或者可能是一个模块),它们可能没有真正的伤害,并且它们可能使你的代码更具可读性。

我的观点是,你需要理解反模式并做出推理判断关于何时何地避免它们。只是采取“我将从不做X而因为它是一种反模式”的立场意味着有时你会排除可接受的,甚至是好的解决方案。

答案 1 :(得分:5)

真正的问题是这个成语在伪typedef 和客户端代码之间创建了一个高度耦合。但是因为您私下使用FooBarMap,所以没有真正的耦合问题(它们是实现细节)。

<强> NB

现代Java IDE应该有助于处理复杂的泛型类型。

答案 2 :(得分:2)

对于公共接口,我不喜欢看泛型类型,因为它们没有意义。让我看到一个带有HashMap参数的方法&lt; Long,Map&lt; Integer,String&gt;&gt;就像foo(int,int,int,void *,int)之类的C方法一样。拥有一个真正的类型只会使代码更容易阅读。对于公共接口,最好创建包装HashMap的FooBarMap&lt; Long,Map&lt; Integer,String&gt;&gt;而不是'typedef',但对于课堂内部使用,我看不到任何缺点。

答案 3 :(得分:0)

如果没有这个伪类型,我宁愿写

private Map<Long,Map<Integer,String>>[] maps;

如果我有一天决定将实现类从HashMap更改为TreeMap或Java7GreatEnhancedWonderfulMap :-)那么什么都不会破坏。但是有了这个,你就陷入了HashMap的困境。好吧,你可以做:

interface FooBarMap extends Map<Long,Map<Integer,String>> { };
class FooBarHashMap extends HashMap<Long,Map<Integer,String>> implements FooBarMap{ };

但它变得越来越麻烦。

答案 4 :(得分:0)

在将其置于公共界面时,他对此有一个很好的观点。这个成语模仿某种形式的语法糖,它不应该影响你向客户展示的东西。

但我认为没有充分的理由不在本地使用它,只要它让你的生活更轻松,代码更具可读性 - 而且你知道自己在做什么。布莱恩可以在任何情况下对其进行概括和强烈建议,但这是他的哥特感觉:p

答案 5 :(得分:0)

如果您只在一个小的本地化代码单元中使用它,那么问题就很小,是真的。

事情是,收益也是如此:你的程序可能甚至不会在文本上变小,直到你引用伪typedef 5次,这意味着它可见的区域必须是非平凡的。

我可能不会重写执行此操作的代码,但这似乎是一个不好的习惯。