MVC体系结构的设计思想实现了将什么和什么分开,MVC体系结构风格

  MVC体系结构的设计思想实现了将什么和什么分开,MVC体系结构风格

  第2章讨论了如何处理Swing组件的事件生产者和消费者。我们了解了Swing组件的事件处理是如何超越原始AWT组件的事件处理功能的。在这一章中,我们将进一步深入Swing组件设计,讨论称为模型-视图-控制器(MVC)的架构。

  3.1理解MVC流程

  在1980年首次引入Smalltalk之后,MVC架构是第2章中描述的观察者模式的一种特殊形式。MVC的模型部分存储组件的状态,作为主体使用。MVC的视图部分作为主体的观察者来显示模型状态。创建一个视图控制器,它定义了用户界面如何响应用户输入。

  MVC通信

  图3-1显示了MVC元素是如何通信的——在这个例子中,使用了Swing的多行文本组件JTextArea。从MVC的角度来看,JTextArea是MVC架构的视图部分。组件内部显示的是一个文档,它是JTextArea的模型。存储JTextArea的状态信息,比如文本内容。JTextArea中有一个InputMap格式控制器。他将键盘输入映射到ActionMap中的命令,这些命令映射到可以通知文档的TextAction对象。当通知发生时,Document创建一个DocumentEvent并将其发送回JTextArea。

  3.1.2 Swing组件的Swing委托

  这个例子展示了Swing world中MVC架构的一个重要方面。视图和控制器之间需要进行复杂的交互。Swing design将这两个元素合并到一个委托对象中,以简化设计。这导致每个Swing组件都有一个UI委托,负责呈现当前组件状态和处理用户输入事件。

  有时,用户事件会导致不影响模型的视图变化。例如,目标位置是视图的一个属性。模型不关心光标位置,只关心文本内容。影响光标位置的用户输入不会传输到模型。相反,影响文档内容的用户输入(如按back键)将被传递。按下返回键将导致角色从模型中移除。由于这种组合,每个Swing组件都有一个UI委托。

  为了演示,图3-2显示了带有模型和UI委托的JTextArea组合。JTextArea的UI委托从TextUI接口开始,基本上是在BasicTextUI中实现的。相应地,它由JTextArea的BasicTextAreaUI具体化。BasicTextAreaUI创建一个视图,可以是平面视图或WrappedPlainView。在模型方面,事情要简单得多。文档接口由AbstractDocument类实现,然后由PlainDocument具体化。

  组件将在第15章和第16章中更全面地解释。如图3-2所示,文本组件的使用涉及很多东西。大多数情况下,我们不需要处理到图中所示的程度。然而,所有这些类都在幕后工作。MVC架构的UI委托部分将在第20章自定义委托时进一步讨论。

  3.2共享数据模型

  因为数据模型只存储状态信息,所以我们可以在多个组件之间共享模型。然后每个组件视图可以用来修改模型。

  在图3-3所示的例子中,可以使用三个不同的JTextArea组件来修改文档模型。如果用户修改了JTextArea的内容,模型也会改变,因此其他文本区域会自动反映更新后的文档状态。对于任何文档视图,不需要手动通知其他视图共享模型。

  数据共享可以通过以下两种方式实现:

  我们可以创建一个独立于任何组件的数据模型,并通知所有组件使用这个数据模型。

  我们可以先创建一个组件,从第一个组件获取模型,然后与其他组件共享。

  JFrame frame=new JFrame(共享样本);

  frame . setdefaultcloseoperation(JFrame。EXIT _ ON _ CLOSE);

  container content=frame . getcontentpane();

  JTextArea textarea 1=new JTextArea();

  document document=textarea 1 . get document();

  JTextArea textarea 2=new JTextArea(document);

  JTextArea textarea 3=new JTextArea(document);

  content.setLayout(新的BoxLayout(content,BoxLayout。y _轴));

  content.add(新JScrollPane(textarea 1));

  content.add(新的JScrollPane(textarea 2));

  content.add(新JScrollPane(textarea 3));

  frame.setSize(300,400);

  frame . set visible(true);

  event queue . invoke later(runner);

  }

  图3-4显示了编辑共享文档后程序的样子。请注意,这三个文本区域具有查看(或修改)文档不同部分的功能。例如,它们不仅限于在末尾添加文本。这是因为每个文本区域分别管理位置和光标。位置和光标是视图的属性,而不是模型的属性。

  3.3了解预定义的数据模型

  当使用Swing组件时,理解每个组件背后的数据模型是有益的,因为数据模型存储了它们的状态。理解每个组件的数据模型有助于我们将可见的组件(视图部分)与其逻辑(数据模型部分)分开。比如理解了这种分离,就明白为什么JTextArea内部的光标位置不是数据模型部分,而是视图部分了。

  表3-1提供了Swing组件的完整列表,每个组件都描述了数据模型和具体实现的接口。如果一个组件没有被列出,它从它的父类继承数据模型,比如AbstractButton。此外,在某些情况下,将使用多个接口来描述一个组件,因为数据存储在一个模型中,而数据选择在另一个模型中。比如JComboBox,MutableComboBoxModel接口就是从ComboBoxModel扩展而来的。预定义的类不仅实现了ComboBoxModel接口,还实现了MutableComboBoxModel接口。

  Swing组件模型

  当直接访问一个组件的模型时,如果我们修改了模型,所有注册的视图都会被自动通知。因此,这将使视图重新验证自己,以确保组件显示其正确的当前状态。这种自动传播状态变化的特性是MVC如此流行的原因之一。此外,MVC架构的使用有助于程序在随着时间和复杂性而修改时变得更容易维护。如果我们改变了可视化组件库,我们就不再需要担心丢失状态信息。

  3.4总结

  本章简要介绍了Swing组件如何使用修改后的MVC架构。我们讨论修改后的MVC架构的组成,以及一个特定的组件JTextArea如何映射到这个架构。此外,本章还讨论了组件之间的数据模型共享,并列出了不同Swing组件使用的所有数据模型。

  在第4章中,我们将开始了解组成Swing库的各个组件。此外,当我们检查Swing库中的基本JComponet组件时,我们将讨论Swing组件的类层次结构。

MVC体系结构的设计思想实现了将什么和什么分开,MVC体系结构风格