Шаблоны проектирования для облегчения / изменения видимости объекта - PullRequest
0 голосов
/ 24 июня 2019

Проблема

Я продолжаю сталкиваться с этой парадигмой, где мне приходится писать функции вида maybeUpdateEnabled, где я изменяю одну переменную, которая определяет видимость, и должна проверять нагрузку других.

Пример

Представьте, что у меня есть следующие данные (для удобства представлены здесь в виде строк):

["apple", "pear", "tomato", "celery", "red pepper"]

, и я предоставляю пользователю графический интерфейс с двумя кнопками-переключателямиодин - для фильтрации всего красного, а другой - для овощей.Пользователь сначала отфильтровывает все красные, а затем все овощи, и остаются только груши.Когда пользователь затем переключает красный переключатель, red peppers, которые были первоначально отфильтрованы, все еще должны быть невидимыми, так как они все еще скрыты через овощной фильтр.

Вопрос

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

Редактировать

Я также хотел бы добавить, что это не обязательно вопрос «как мне это сделать», а скорее «как сделать так, чтобы это не причиняло боль в шее».Я могу иметь любое количество n полей, ни одно из которых не имеет каких-либо конкретных гарантий того, какие условия могут отфильтровывать любое количество m объектов.У меня есть временное исправление для этой цели, но я бы хотел воспользоваться практикой рефакторинга для обеспечения чистого API без необходимости реорганизовывать почти все.

Edit 2

ХотяЯ не могу опубликовать код, я могу абсолютно вам сказать, что используется куча JFXToggleButtons, и слушатели подключаются к «сигналу» selectedProperty, который, на мой взгляд, создает очень тесную связь между представлениемМодель и контроллер, поскольку представление и контроллер, по сути, являются одними и теми же базовыми структурами данных и классами (что много отстой).Изменение свойств без графического интерфейса имеет то преимущество, что автоматически обновляет контроллер, но, к сожалению, генерирование изменений для каждого отдельного изменения свойства в соответствии с приведенным выше редактированием ужасно неэффективно (и да, я его профилировал).

1 Ответ

1 голос
/ 25 июня 2019

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

Вы, очевидно, заинтересованы в семантике строк. Чтобы упростить задачу, вы должны использовать объекты для представления строковых данных. Критерием фильтра может быть список тегов в виде EnumSet<E>.

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

public enum Tags
{
  RED, YELLOW, GREEN, VEGETABLE, FOOD, FRUIT, MEAT, SWEET, HOT, SPICEY
}

Затем подготовьте объект данных для фильтрации:

public interface IFilterable
{
  EnumSet<Tags> getTags();
  void setTags(EnumSet<Tags> tags);
}

public class DataObject implements IFilterable
{
  private EnumSet<Tags> tags; 
  public EnumSet<Tags> getTags() { 
    return this.tags; 
  }

  public void setTags(EnumSet<Tags> tags) { 
    this.tags = tags; 
  }
}

Фильтрация теперь может быть легко достигнута с использованием потоков или класса javafx.collections.transformation.FilteredList<E>.

Чтобы показать только красные овощи (например, когда пользователь изменяет сборщик), используйте:

public static void main(String[] args) {
  ObservableList<DataObject> unfilteredObjects = FXCollections.observableArrayList(new DataObject(EnumSet.of(Tags.RED, Tags.VEGETABLE)), new DataObject(EnumSet.of(Tags.RED, Tags.FRUIT)));

  // A filtered collection that contains only red vegetables
  // In this case the size of redVegetables will be 1
  EnumSet<Tags> filterCriteria = EnumSet.of(Tags.RED, Tags.VEGTABLE);
  Predicate<DataObject> filterPredicate = dataObject -> dataObject.getTags().containsAll(filterCreiteria);
  FilteredList<DataObject> redVegetables = new FilteredList<>(unfilteredObjects, filterPredicate);
}

Когда вы теперь привязываете ListView к ObservableList (или FilteredList, поскольку он реализует ObservableList), будут отображаться только отфильтрованные элементы, а исключенные элементы автоматически исчезают с экрана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...