2010-09-30 51 views
4

编辑:我已经接到了几个答案,那说什么我的问题已经说的。我真正感兴趣的是找到确凿的参考材料。Java Map反模式?


我在看或多或少遵循这一模式的代码示例:

Map<String, List> getListsFromTheDB() { 
    Map<String, List> lists = new HashMap<String, List>(); 

    //each list contains a different type of object 
    lists.put("xList", queryForListOfXItems()); 
    lists.put("yList", queryForListOfYItems()); 

    return lists; 
} 

void updateLists() { 
    Map<String, List> lists = getListsFromTheDB(); 
    doSomethingWith(lists.get("xList")); 
    doSomethingWith(lists.get("yList")); 
} 

我的感觉是,这是一个反模式。什么编码器应该做的是创造出可以返回一个类,像这样:

class Result { 
    private final List<X> xList; 
    private final List<Y> yList; 

    public Result(xList, yList) { 
    this.xList = xList; 
    this.yList = yList; 
    } 

    public List<X> getXList() { xList; } 
    public List<Y> getYList() { return yList; } 
} 

这将更加类型安全,避免过度概括一个非常具体的问题,更不易在运行时错误。

任何人都可以指向我指定,你应该避免这种模式的任何权威的参考材料?或者,如果它实际上是一个很好的模式,请给出理由。

+1

请注意,总是有两种类型的返回列表;它不会因使用情况而异。 – RMorrisey 2010-09-30 00:34:29

+0

你在说什么听起来很合理,因为你总是知道'doSomething'的输入是xList和yList。但是,如果你只是想批量处理返回的列表而不参考每个单独的列表,那么返回某种Map/List/Set结构确实有意义。 – Strelok 2010-09-30 00:36:45

+0

我认为这是一个反模式,是的。 – ColinD 2010-09-30 01:09:50

回答

1

我没有任何权威材料,但我的直觉是,除非在实际代码中出现更复杂的事情,否则使用Map这种方式并不会影响到我。实际上,Result类感觉有点像矫枉过正。

+2

难道你不打扰你,如果你输入“xlist”而不是“xList”,编译器不会捕获你?在我的实际代码中,这两个方法在不同的包中有不同的类。你可以通过使用常量来解决这个问题,但是真的,为什么要首先引入潜在的问题点? – RMorrisey 2010-09-30 00:38:02

+3

我想它确实有一点。再想一想,我真的只想看两种方法,getXListFromTheDB()和getYListFromTheDB()。 – 2010-09-30 01:26:44

+0

我同意在示例中使用两个单独的方法会更干净,但我认为那不重要。 =) – RMorrisey 2010-09-30 02:33:44

3

我认为这一点是列表的数量是固定的。由于您确保代码使用2个列表,因此地图有点过度泛化。

所以“类结果”是更好的,我认为。

1

我同意你的看法。 显然这个家伙很懒,并且使用Map来避免创建一个新类。 副作用是需要使用getListsFromTheDB()的代码可读性较差,正如您所提到的那样,更容易出错。

当然,还有就是在调用者创建列表中选择:

void fillFromTheDB(List<X> xList, List<Y> yList) { 
    //each list contains a different type of object 
    xList.addAll(queryForListOfXItems()); 
    yList.addAll(queryForListOfYItems()); 
} 

void updateLists() { 
    List<X> xList = new ArrayList<X>(); 
    List<Y> yList = new ArrayList<Y>(); 
    fillFromTheDB(xList, yList); 
    doSomethingWith(xList); 
    doSomethingWith(yList); 
} 
+0

编辑这个问题,以澄清我在找什么 – RMorrisey 2010-09-30 12:29:46

4

我说这取决于上下文。

如果您返回地图,来电者必须知道'魔术'键"xList""yList"才能将实际数据从地图中取出。我的意思是作为魔术常量的魔法。 (你可以迭代地图来找到魔术键,但这只是一个技巧。)通过使用地图,你实际上已经隐藏了数据,使得难以得到想要的东西(x和yLists)。

的魔术常量不必如此神奇。如果"xList""yList"将是数据库中的表名(或任何外部字符串),那么我期望从表名到对象列表得到映射。有人可能会添加/重命名/删除表格。 (或者,也许更漂亮,我想能够每桌查询像getListFromTheDB("xList");。)

在你的代码得到这个方法

queryForListOfXItems(); 

但这闻起来像硬编码的Xlist和yList。因此,(国际海事组织)制定地图是一个不好的选择。

+0

编辑这个问题,以澄清我在找什么 – RMorrisey 2010-09-30 12:28:47

+0

@Rorrisey - 幻数(或常量)是一个反模式,所以这种风格要求一个。但我不知道是否有'地图反模式'。也许现在有了;) – Ishtar 2010-09-30 15:24:18