2012-04-09 2 views
1

У меня есть список MyObjects, которые мне нужно разделить на три группы:OO шаблон для разделения коллекции на группы

  1. Known хорошо (держать)
  2. Известный плохой (отклонить)
  3. Непризнанный (поднять предупреждение)

MyObject содержит различные свойства, которые должны быть изучены, чтобы определить, какой из 3-х групп поместить объект.

Моя первоначальная реализация (Java) просто берет Список в его конструкторе и выполняет сортировку там. Псевдокод:

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

Я знаю, что вы немного недовольны чрезмерным или неправильным использованием функциональных парадигм Гуавы, но, как часть команды Guava, вы не собираетесь предлагать использование 'Predicate' и 'Iterables.filter() '? –

+0

Абсолютно нет. Для начала OP хочет разбить список на три категории. Даже используя 'Iterables.filter' - OP будет использовать' Predicate', а не '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' , а не один. Мало того, что функциональные идиомы делают это менее читаемым, это сделает его менее эффективным. –

+0

Я был занят редактированием своего сообщения, чтобы использовать Predicates, прежде чем увидел ваш ответ. Я вижу вашу точку зрения, поскольку она относится к вопросу, как прямо спрашивается. Наверное, я думал о том, что было «зависеть» от вопроса. Действительно ли цель состоит в том, чтобы иметь три физических коллекции или была цель иметь средства для классификации каждого элемента одной коллекции по мере необходимости? Если последнее, то было бы неуместным предлагать использование предикатов в качестве распределенных классификаторов, если вы не хотите добавлять логику к классифицируемым объектам? –

0

Может быть несколько подходов. Если проблема является общей или повторяющейся, вы можете определить интерфейс с методом для классификации объектов.

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

}

Таким образом, вы могли бы изменить реализацию логики легко.

0

Другая идея - использовать Цепь ответственности.

Ваш MyObjectFilterer содержит ссылку на трех объектов GoodFilterer, BadFilterer и UnrecognizedFilterer. Каждый из них содержит следующие методы: addMethod (объект MyObject), getObjects() и addFilter(). Конечно, они должны реализовать интерфейс Фильтр.

С помощью метода addFilter вы можете построить цепочку. так что GoodFilterer содержит ссылку на BadFilterer и это одна содержит ссылку на UnrecognizedFilterer

Теперь вы идете через ваш список MyObjects и вызывать метод добавления на GoodFilterer (первый в этой цепочке). Внутри метода добавления вы решаете, хорошо ли это, чем вы его сохраняете и завершаете, если не передать его на BadFilterer.

Вы держите свои три метода для получения хорошего/плохого и непризнанное, но вы будете передать это GetObjects() метод из соответствующего Filterer

Преимущество заключается в том, что логика, если это теперь есть хороший/плохой или непризнанный.

The Downside вам понадобится 3 новых класса и 1 интерфейс.

Но, как я уже сказал, это просто другая идея, что вы могли бы сделать.

+1

Похоже, что категории в этом случае являются взаимоисключающими и, следовательно, могут быть взаимозависимыми (т. Е. Могут быть плохими или непризнанными, если сначала известно, что они НЕ хороши). Поэтому я не уверен, что вы хотите отделить логику вычисления good/bad/unrecognized –

0

Вы должны упростить, насколько это возможно. Просто сделайте статический метод в MyObjectFilter со следующей подписью:

public static Фильтр списка объектовMyObjects (данные списка, группа групп).

Группа перечисление с тремя значениями, и он может быть использован в качестве атрибута класса MyObject

+0

, вероятно, не очень хорошо, чтобы сделать перечисление свойством объектов, потому что если у объектов есть другие изменяемые поля, используемые в категоризации, их классификация может измениться и вам нужно будет сохранить свойство категоризации в синхронизации с любыми изменениями в объекте. Лучше сохранить логику/свойства категоризации, внешние по отношению к классу. –

+0

Извините, я не все правильно понял из вашего вопроса. Я думал, что Group действительно принадлежит к вашему классу как поле. Я бы предпочел использовать один статический метод и использовать групповое перечисление (переименованное в FilterOption) в качестве аргумента метода. –

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); 

хорошая вещь об этом решения не должны создавать/публиковать методы доступа для каждой категории (если вы не хотите), и если создаются новые категории, вы также не добавляете новых аксессуаров - только новое перечисление и дополнительную классификационную логику.

Смежные вопросы