2012-04-09 86 views
1

我有我需要分成三组MyObjects列表:OO模式

  1. 已知良好(保持)
  2. 已知不良(拒绝)
  3. 无法识别(提高警报)

为MyObject包含必须进行检查,以确定哪一个3组,使对象在各种性能。

我的初始实现(Java)只是在其构造函数中接受一个List并在那里进行分类。伪代码:

class MyObjectFilterer { 
    public MyObjectFilterer(List<MyObject> list) { 
    // triage items here 
    } 
    public List<MyObject> getGood() { 
    // return sub-list of good items 
    } 
    public List<MyObject> getBad() { 
    // return sub-list of bad items 
    } 
    public List<MyObject> getUnrecognized() { 
    // return sub-list of unrecognized items 
    } 
} 

此实施的任何问题?有更好的OO选择吗?

回答

2

我可能会更喜欢静态工厂方法做过滤,那然后调用私有构造函数,这三个过滤列表,下面的从未做任何严肃的工作在一个构造良好的代码实践。除此之外,这看起来很好。

+0

我知道你是一个有点向下过度使用或错误使用番石榴功能范式,但作为番石榴团队的一员,你不会建议使用Predicate's和'Iterables.filter的'() '? – 2012-04-09 16:54:53

+0

绝对不是。对于初学者,OP希望将列表分成三个不同的类别。即使使用'Iterables.filter' - OP将使用'Predicate's,而不是'Function',并且记住没有'Lists.filter'方法 - 这需要三次遍历目标列表,而不是一个单一的。功能性成语不仅会降低可读性,而且会严重降低效率。 – 2012-04-09 16:57:32

+0

在我看到您的回复之前,我正忙于编辑我的帖子以使用Predicates。我明白你的观点,因为它适用于直接询问的问题。我想我正在考虑这个问题背后的可能性。目标实际上是有三个物理集合还是目标是有必要根据需要对单个集合中的每个元素进行分类?如果后者,那么建议使用Predicates作为分布式分类器仍然不合适,如果您不想将逻辑添加到被分类的对象中? – 2012-04-09 17:08:10

0

可能有多种技术途径。如果问题足够通用/重复,则可以使用方法来定义接口,以对对象进行分类。

interface Selector { 
    public boolean isGood(MyObject myObject); 
    public boolean isBad(MyObject myObject); 
    public boolean isUnknown(MyObject myObject); 

}

这种方法你可以很容易地改变逻辑实现。

0

的其他想法是使用责任链。

MyObjectFilterer包含三个对象GoodFiltererBadFiltererUnrecognizedFilterer参考。其中每个包含以下方法:addMethod(MyObject对象),getObjects()addFilter()。当然,他们必须实现一个接口Filterer

有了可以构建链addFilter方法。从而使GoodFilterer包含对BadFilterer参考,这其中蕴含的UnrecognizedFilterer

现在,你通过你的MyObjects列表,并呼吁GoodFilterer add方法(参考在这条链上的第一个)。在里面你决定这是不是好,比你把它和完成工作,如果不把它传递到BadFilterer add方法。

你保持你的三种方法获得的相应Filterer

的好处是逻辑,如果这是好/坏和未确认的,但你将它传递给getObjects()方法好/坏或无法识别的一个现在是分开的。

下行则需要3个新的类别和1接口。

但就像我说的,这只是一个其他的想法,你能做些什么。

+1

看来,在这种情况下,类别是互相排斥的,因此可能是相互依赖的(即,如果首先知道它不是好的,那么它们只能是坏的或不能识别的)。所以我不确定你想分开计算好/坏/无法识别的逻辑 – 2012-04-09 18:37:14

0

你应该简化,因为它是可能的。只是让静态的方法MyObjectFilter具有以下特征:

公共静态列表filterMyObjects(列表数据,组组)。

集团是枚举有三个值,它可以被用来作为的MyObject类的属性

+0

可能不好使枚举成为对象的属性,因为如果对象在分类中使用了其他可变字段,它们的分类可能会改变并且您必须保持分类属性与该对象的任何更改同步。更好地保持课堂外的分类逻辑/属性。 – 2012-04-09 20:45:35

+0

对不起,我没有正确理解你的问题。我认为Group实际上属于你的班级。我仍然希望有一个静态方法,并使用组枚举(在FilterOption中重命名)作为方法的参数。 – 2012-04-10 21:14:55

0

我可能会尝试这样的:

enum MyObjectStatus { 
    GOOD, BAD, UNRECOGNIZED; 
} 

class MyObjectFilterer { 
    private MyObjectStatus getStatus(MyObject obj) { 
    // classify logic here, returns appropriate enum value 
    } 

    // ListMultimap return type below is from Google Guava 
    public ListMultimap<MyObjectStatus, MyObject> classify(List<MyObject> objects) { 
    ListMultimap<MyObjectStatus, MyObject> map = ArrayListMultimap.create(); 
    for(MyObject obj: objects) { 
     map.put(getStatus(obj), obj); 
    } 
    } 
} 

呼叫分类()得到一个Multimap之,并提取每个类别根据需要的东西,如:

List<MyObject> good = map.get(GOOD); 
List<MyObject> bad = map.get(BAD); 
List<MyObject> unknown = map.get(UNRECOGNIZED); 

有关该解决方案的好处是,你不必创建/发表关于每个类别的访问方法(除非你想),并如果创建了新的类别,您也不会添加新的访问器 - 只是新的枚举和附加的分类器逻辑。