减轻/更改对象可见性的设计模式

时间:2019-06-24 14:55:36

标签: java javafx design-patterns

问题

我一直在遍历此范式,在该范式中,我必须编写maybeUpdateEnabled形式的函数,在其中我更改一个确定可见性的变量,并对照其他变量进行检查。

示例

想象一下我有以下数据(为方便起见,在这里表示为字符串):

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

,我为用户提供了一个带有两个切换按钮的GUI,一个用于过滤所有红色的东西,另一个用于过滤所有蔬菜的东西。用户首先滤除所有红色,然后滤除所有蔬菜,仅保留梨。当用户随后切换红色开关时,最初被过滤掉的red peppers应该仍然不可见,因为它们仍通过蔬菜过滤器隐藏。

问题

是否有任何设计模式可以缓解这种情况?我当时正在考虑使用位掩码或某种形式的堆栈,但我认为我无法从逻辑上避免使用maybeUpdate范式,这对我来说是一种可怕的代码味道。

编辑

我还想补充一点,这不一定是“我该怎么做”的问题,而是“我该如何使这不是脖子上的痛苦”。我可以有任意数量的n个字段,而这些字段都没有任何特定保证可以确定哪些条件可能会过滤掉任意数量的m个对象。为此,我在生产中有一个临时修复程序,但我想进行重构以提供一个干净的API,而不必重构几乎所有内容。

编辑2

虽然我无法发布代码,但我绝对可以告诉您,正在使用一堆JFXToggleButtons,并且侦听器正在连接到selectedProperty“信号”,我认为这是在视图,模型和控制器之间建立了非常紧密的耦合,因为视图和控制器实际上是相同的基础数据结构和类(这很麻烦)。在不使用GUI的情况下更改属性的好处是可以自动更新控制器,但是不幸的是,每次上述属性更改都会发出更改,而上述编辑则效率极低(是的,我已经对其进行了概要分析)。

1 个答案:

答案 0 :(得分:1)

要过滤集合对象,过滤器需要一个条件。此条件必须是要过滤的对象的属性。过滤纯字符串时,条件可以是词汇,语法,句法或语义。

您显然对字符串的语义感兴趣。为了使事情变得容易,您应该使用对象来表示字符串数据。过滤条件可以是EnumSet<E>形式的标签列表。

首先定义可用标签的列表。您可以将此列表公开给UI,也可以通过UI对其进行扩展(扩展标签列表仍然会使您的数据对象关闭以进行修改):

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)时,只有已过滤的项目会显示,而排除的项目会自动从显示。