Дизайн шаблона для фильтрации коллекции предметов? - PullRequest
15 голосов
/ 26 октября 2009

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

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

Задача проектирования, связанная с написанием такой функции фильтрации, должна быть чем-то, что МНОГИЕ разработчики сделали, и, безусловно, должен быть какой-то шаблон проектирования, наиболее подходящий для этой задачи.

Кто-нибудь?

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

Ответы [ 6 ]

6 голосов
/ 26 октября 2009

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

  1. Базовая коллекция должна быть неизменной после фильтрации
  2. Результат не является постоянным

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

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

Например:

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, хотя это может повлиять на достоверность итераторов (как обычно).

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

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

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

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

1 голос
/ 26 октября 2009

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

1 голос
/ 26 октября 2009

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

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

1 голос
/ 26 октября 2009

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

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

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

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

0 голосов
/ 03 июля 2013

Посмотрите, может ли http://en.wikipedia.org/wiki/Criteria_Pattern помочь вам. Основан на спецификации

0 голосов
/ 26 октября 2009

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

...