技术开发 频道

Swing 模型过滤

  模型过滤的基本概念利用了 Swing 组件对模型类的底层实现缺乏了解这一事实。下图说明了这种典型的关系:

  模型过滤器是实现了模型接口、但并不真正包含数据的类。模型过滤器在组件与其模型之间进行协调。模型过滤器可以重新解释模型所提供的信息,并且可以更改所提供的数据元素个数、数据的顺序以及数据本身。

  在本例中,过滤器类是将一个现有模型类作为其数据源来实例化的。在模型过滤器的一般实现中,对 API 方法的调用将委托给源模型。

  由于此 API 是统一实现的,因此完全可以在组件与其模型之间“叠放”多个过滤器。注意,每个过滤层都要求每个 API 调用穿过一个附加的间接层;如果过滤层过于复杂,则很可能造成性能瓶颈。

  基本过滤器

  下面显示的抽象类是作用于 JList 组件之上的模型过滤器的基类。其唯一的构造函数要求,模型过滤器的每个实例都要引用某个底层的模型数据。该数据既可以是另一个模型过滤器,也可以不是;在这两种情况下,过滤器的行为是相同的。

  模型过滤器基类

1 package com.ketherware.models;
2 import javax.swing.*;
3 public abstract class AbstractListModelFilter extends AbstractListModel
4 {
5 // 用来保存被过滤模型的引用
6 protected ListModel delegate;
7 // 构造函数 ― 接受单个参数,其中包含被过滤模型的引用
8 public AbstractListModelFilter(ListModel delegate)
9     {
10   this.delegate = delegate;
11     }
12 public ListModel getDelegate()
13     {
14   return this.delegate;
15     }
16 public int getSize()
17     {
18   // 委托给过滤器目标
19   return delegate.getSize();
20     }
21 public Object getElementAt(int index)
22     {
23   // 委托给过滤器目标
24   return delegate.getElementAt(index);
25     }
26 public void addListDataListener(ListDataListener listener)
27     {
28   // 委托给过滤器目标
29   delegate.addListDataListener(listener);
30     }
31 public void removeListDataListener(ListDataListener listener)
32     {
33   // 委托给过滤器目标
34
35 delegate.removeListDataListener(listener);
36     }
37 }
38

  该类相当于一种“空”过滤器,它不更改任何底层数据。因此,它没有什么特别的意义。ListModel 过滤器类的实际实现将覆盖该抽象类的方法,以便以不同的方式呈现底层数据。

  您可以通过实现过滤器来改变底层数据事件的特性。为了使对模型过滤器的讨论更易于理解,本文的示例都只针对不可变的数据模型,即不触发任何模型事件的类。

  缺省模型适合于要求不高的一般应用。但是,您应该了解这些缺省类都是为通用目的而设计的,因此,在对性能有严格要求的情况下,它们通常表现不佳。同样,许多常用的模型都是作为可变模型来实现的,即,模型的数据可随时间变化。当已知数据为静态数据时,这些额外的行为可能是多余的。因此,您可能想另外构建模型类,去掉由事件传播所导致的额外开销。

  不可变模型

  在许多情况下,根据模型的底层数据是否可变对模型进行分类很有用。在数据不会变化的情况下,可以实现不可变的数据模型,这种模型不实现用于监听数据变化的监听程序。Swing 模型接口的缺省实现假定数据是可变的。

  不可变模型的创建过程相当简单。您可以创建一个具体类,该类可提供模型接口,但为与事件相关的活动所提供的所有方法都不执行任何操作。根据模型要作为一般模型使用,还是作为专用模型使用,您既可将此不可变模型实现为一个抽象类,也可将其实现为一个具体类。

  下面的示例是一个不可变的列表模型,我设计它时希望它非常通用,并且允许将支持 java.util.List 集合接口的任何对象用作数据源。返回的数据是一个笼统的 Object 类型;如何显示对象留待 JList 及其相关绘制程序解释。

  不可变模型的示例

1 package com.ketherware.models;
2 import java.util.*;
3 import javax.swing.*;
4 public abstract class ImmutableListModelFilter extends AbstractListModel
5 {
6 // 用来保存被过滤模型的引用
7 protected List collection;
8 // 构造函数 ― 接受单个参数,其中包含被过滤模型的引用
9 public AbstractListModelFilter(List collection)
10     {
11   this.collection = collection;
12     }
13 public List getCollection()
14     {
15   return this.collection;
16     }
17 public int getSize()
18     {
19   // 委托给集合
20   return collection.size();
21     }
22 public Object getElementAt(int index)
23     {
24   // 委托给过滤器目标
25   return collection.get(index);
26     }
27 public void addListDataListener(ListDataListener listener)
28     {
29   // 覆盖为‘空操作’
30     }
31 public void removeListDataListener(ListDataListener listener)
32     {
33   // 覆盖为‘空操作’
34     }
35 }
36

  下面将讨论四种类型的过滤器:替换、排序、排除和包含。

0
相关文章