Дизайн шаблона для фильтрации коллекции предметов?

Представьте типичный тип приложения, где у вас есть список элементов с разными свойствами. Например. древовидный вид с 100 наименованиями, каждый из которых имеет имя, рейтинг, ранжирование в пределах самых горячих предметов на планете и т.д. Возможно, существует также много-ко-многим отношениям между элементами и каталогами предметов, или между элементами и создателями элементов и т.д. и т.д.

Теперь этому приложению, естественно, нужна система фильтрации. Например. где я могу создавать сложные фильтры с множеством условий всех видов, между данными в разных отношениях.

Задача проектирования записи такой функции фильтрации должна быть чем-то большим, чем было сделано разработчиками, и наверняка должен быть какой-то шаблон дизайна, который наиболее подходит для задачи.

Кто-нибудь?

Изменить:. Переключилось на wiki сообщества, так как я подозреваю, что для этого не существует шаблона отраслевых факторов. Вопрос, который в целом сформулирован, я думаю.

Ответ 1

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

  • Основная коллекция не должна изменяться после фильтрации
  • Результат не является постоянным.

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

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

Например:

Collection myCollection;
Predicate myFilter;

// Nothing is computed here
View<Predicate> myView(myCollection, myFilter);

// We iterate until we find the first item in the collection that satisfies
// the Predicate, and no more, to initialize `begin`
View<Predicate>::Iterator begin = myView.begin(), end = myView.end();

Чистым преимуществом является то, что если вам (скажем) нужны только 10 первых предметов, тогда вы будете применять только предикат столько, сколько необходимо, чтобы найти эти 10 в первую очередь и не более.

Кроме того, нет копии задействованных элементов, и ваше представление будет обновлено, даже если вы измените myCollection, хотя это может повлиять на действительность итераторов (как обычно).

Проблема заключается в том, что (если вы не реализуете кэширование), результат вычисляется каждый раз.

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

Что касается предложенного шаблона стратегии, вы можете, как правило, создавать свой фильтр по блоку с помощью Composite Pattern, а затем передавать объект, построенный таким образом как стратегия.

Композитный шаблон особенно подходит для представления результата синтаксического выражения, например, вы можете захотеть взглянуть на деревья выражений, чтобы получить представление.

Ответ 2

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

Например, LINQ имеет хороший способ сортировки, используя деревья выражений.

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

Если вы работаете над чем-то вроде javascript, тогда функция сортировки может быть создана на лету.

Ответ 3

Вы ищете реляционную базу данных, из которой вы можете использовать SQL. Вы можете встать на полную ставку и подключиться к ней из своего приложения, или вы можете сделать что-то между полной базой данных и прямыми объектами. В Java, например, вы можете использовать базу данных в памяти, такую ​​как HSQLDB/JavaDB, и использовать ее. Вы также можете использовать JoSQL, который позволит вам работать с SQL непосредственно на ваших объектах без базы данных вообще.

В качестве альтернативы, если вы хотите самостоятельно запрограммировать эту вещь, вы должны начать с сохранения двух копий ваших данных. Один из них - ваш полный набор данных, другой - ваш взгляд на данные после фильтрации. Затем вы создадите индекс для своих данных для каждого столбца, сортируя данные и сохраняя свою позицию в отсортированном списке. Такая же настройка работает для соответствия фильтра. Если что-то соответствует фильтру для столбца, дайте ему 1 или 0, если нет. Затем, когда кто-то переключает порядок сортировки, вы копируете свои данные из полного списка в список просмотра или когда изменяете информацию об фильтрах, вы должны брать только данные, которые имели совпадение.

Ответ 4

Мне нравится фильтр с предикатом Коллекции Google, и я бы использовал что-то очень похожее, если бы я не мог его использовать. Вы можете проверить этот ответ на аналогичный вопрос для примера реализации. Реализация выполняется на Java, но, ну, вы увидите шаблон.

Ответ 5

Если эти отношения выражаются как RDF и OWL, вы можете использовать инструмент с конечной точкой SPARQL (например, Jena) или аргументом, таким как Pellet. Но без подробностей неясно, что это лучший подход.