Swing和模型-视图-控制器设计模式

在解决一一个问题时,不需要从头做起,而是借鉴过去的经验,或者向做过相关工作的专家请教。设计模式就是一-种方法,这种方法以一种结构化的方式展示专家们的心血。

  近几年来,软件工程师们开始对这些模式进行汇总分类。这个领域的先驱者的灵感来源F建筑师Christopher Alexander的设计模式。他在《The Timeless Way of Building》( 1979年,牛津大学出版) - -书中,为公共和私人居住空间的建筑设计模式进行了分类。下面是一个典型的例子:
  窗户位置  
  每个人都喜欢靠窗户的座位,可以画上凸出去的窗户、低窗台的大窗户以及放在这里的舒适椅子。如果一一个房间中没有这样一个地方,很少有人会感到舒服和安逸。

  如果房间中没有像这样“位置的千个窗户,房息里的人就有可能要做出下列抉择:
  (1)舒适地坐下; (2)要充足的阳光。

  显然,舒适的地方是房间中最想坐的地方,但它们远离窗户,这种冲突不可避免。因此,对于白天长时间逗留的房间,至少要将一个窗户开在“窗户位置”处。  低窗台

  在Alexander的模式分类和软件模式的分类中,每种模式  位置都遵循一种特定的格式。这些模式首先描述背景,即引发设计问题的情形;接着解释问题,通常这里会有几个冲突的因素;最终,权衡这些冲突,给出问题的解决方案。

  在“窗户位置”模式中,背景是在白天逗留时间较长的房窗户位置间。冲突因素就是既想舒适地坐下,又想拥有充足的光线。解决方案是找到-一个“窗户位置”。

在这里插入图片描述
在“模型-视图-控制器”模式中,背景是显示信息和接收用户输人的用户界面系统。有关“模型-视图-控制器”模式将在接下来的章节中讲述。这里有几个冲突因素。对于同一数据来说,可能需要同时更新多个可视化表示。例如,为了适应各种观感标准,可能需要改变可视化表示形式;又例如,为了支持语音命令,可能需要改变交互机制。解决方案是将这些功能分布到三个独立的交互组件:模型、视图和控制器。
模型-视图-控制器模式并不是AWT和Swing设计中使用的唯–模式。下列是应用的另外几种模式:
●容器和组件是“组合(composite)“模式
●带滚动条的面板是“装饰器(decorator)” 模式
●布局管理器是“策略(strategy)" 模式

  设计模式的另外一个最重要的特点是它们已经成为文化的一部分。 只要谈论起模型-视图-控制器或“装饰器”模式,遍及世界各地的程序员就会明白。因此,模式已经成为探讨设计方案的一种有效方法。

  读者可以在Erich Gamma等编著的《Design Patterns-- -Elements of Reusable Object-Oriented Software》( Addison-Wesley出版社,1995 年出版)一书中找到大量的实用软件模式的规范描述,这是一本研究模式运动的书籍。这里再强烈地推荐- -本由FrankBuschmann等编著的《A System of Patterns》,John Wiley & Sons出版社于1996出版。这是一本不错的书籍,相对前一本,这本书更容易读懂。

9.1.2 模型-视图-控制器模式

  让我们稍稍停顿一会儿, 回想一下构成用户界面组件的各个组成部分,例如,按钮、复选框、文本框或者复杂的树形组件等。每个组件都有三个要素:

  ,内容,如:按钮的状态(是否按下权或者文本框的文本。。外观 (颜色,大小等)。.行为(对事件的反应)。
这三个要素之间的关系是相当复杂的,即使对于最简单的组件(如:按钮)来说也是如此。很明显,按钮的外观显示取决于它的观感。Metal按钮的外观与Windows按钮或者Motif按钮的外观就不一样。另外,外观显示还要取决于按钮的状态:当按钮被按下时,按钮需要被重新绘制成另--种不同的外观。而状态取决于按钮接收到的事件。当用户在按钮上点击时,按钮就被按下。

  当然,在程序中使用按钮时,只需要简单地把它看成是一一个按钮,而不需要考虑它的内部工作和特性。毕竟,这些是实现按钮的程序员的工作。无论怎样,实现按钮的程序员就要对这些按钮考虑得细致-些了。毕竟,无论观感如何,他们必须实现这些按钮和其他用户界面组件,以便让这些组件正常地工作。

  为了实现这样的需求,Swing 设计者采用了一-种很有名的设计模式( design pattern):模型.视图-控制器( model-view-controller)模式。这种设计模式同其他许多设计模式一样,都遵循第5章介绍过的面向对象设计中的一一个基本原则:限制一个对象拥有的功能数量。不要用一个按钮类完成所有的事情,而是应该让-一个对象负责组件的观感,另一个对象负责存储内容。模型-视图-控制器(MVC)模式告诉我们如何实现这种设计,实现三个独立的类:

  ●模型(model):存储内容。
  ●视图 (view): 显示内容。
  ●控制器(controller): 处理用户输人。

  这个模式明确地规定了三个对象如何进行交互。模型存储内容,它没有用户界面。按钮的内容非常简单,只有几个用来表示当前按钮是否按下,是否处于活动状态的标志等。文本框内容稍稍复杂一一些,它是保存当前文本的字符串对象。这与视图显示的内容并不一一致一如果内容的长度大于文本框的显示长度,用户就只能看到文本框可以显示的那一部分, 如图所示。

在这里插入图片描述
模型必须实现改变内容和查找内容的方法。例如,一个文本模型中的方法有:在当前文本中添加或者删除字符以及把当前文本作为一一个字符串返回等。记住:模型是完全不可见的。显示存储在模型中的数据是视图的工作。
模型-视图-控制器模式的一个优点是一个模型可以有多个视图,其中每个视图可以显示全部内容的不同部分或不同形式。例如,一个HTML编辑器常常为同一内容在同一时刻提供两个视图:一个WYSIWYG (所见即所得)视图和-一个“原始标记”视图(见图)。当通过某-一个视图的控制器对模型进行更新时,模式会把这种改变通知给两个视图。视图得到通知以后就会自动地刷新。当然,对于一个简单的用户界面组件来说,如按钮,不需要为同- -模型提供多个视图。
在这里插入图片描述
控制器负责处理用户输人事件,如点击鼠标和敲击键盘。然后决定是否把这些事件转化成对模型或视图的改变。例如,如果用户在一一个文本框中按下了一个字符键,控制器调用模型中的“插人字符”命令,然后模型告诉视图进行更新,而视图永远不会知道文本为什么改变了。但是如果用户按下了一个光标键,那么控制器会通知视图进行卷屏。卷动视图对实际文本不会有任何影响,因此模型永远不会知道这个事件的发生。

  上图给出了模型、视图和控制器对象之间的交互。

  在程序员使用Swing组件时,通常不需要考虑模型-视图-控制器体系结构。每个用户界面元素都有一一个包装器类(如JButton或JTextField)来保存模型和视图。当需要查询内容(如文本域中的文本)时,包装器类会向模型询问并且返回所要的结果。当想改变视图时(例如,在一个文本域中移动光标位置),包装器类会把此请求转发给视图。然而,有时候包装器转发命令并不得力。在这种情况下,就必须直接地与模型打交道(不必直接操作视图一这是观感代码的任务)。

  除了“本职工作”外,模型-视图、控制器模式吸引Swing设计者的主要原因是这种模式允许实现可插观感。每个按钮或者文本域的模型是独立于观感的。当然可视化表示完全依赖于特殊观感的用户界面设计,且控制器可以改变它明例如,在一一个语 音控制设备中,控制器需要处理的各种事件与使用键盘和鼠标的标准计算机完全不同。通过把底层模型与用户界面分离开,Swing设计者就能够重用模型的代码,甚至在程序运行时对观感进行切换。

  当然,模式只能作为一种指导性的建议而并没有严格的戒律。没有一种模式能够适用于所有情况。例如,使用“窗户位置”模式(设计模式中并非主要成分)来安排小卧室就不太合适。同样地,Swing设计者发现对于可插观感实现来说,使用模型-视图-控制器模式并非都是完美的。模型容易分离开,每个用户界面组件都有一一个模型类。但是,视图和控制器的职责分工有时就不很明显,这样将会导致产生很多不同的类。当然,作为这些类的使用者来说,不必为这些细节费心。前面已经说过,这些类的使用者根本无需为模型操心,仅使用组件包装器类即可。

在这里插入图片描述

Swing 按钮的模型-视图-控制器分析

  前一章已经介绍了如何使用按钮,当时没有考虑模型、视图和控制器。按钮是最简单的用户界面元素,所以我们从按钮开始学习模型-视图-控制器模式会感觉容易些。对于更复杂的Swing组件来说,所遇到的类和接口都是类似的。

  对于大多数组件来说,模型类将实现一一个名字以Model结尾的接口,例如,按钮就实现了ButtonModel接口。实现了此接口的类可以定义各种按钮的状态。实际上,按钮并不复杂,在Swing库中有-一个名为DefaultButtonModel的类就实现了这个接口。

  读者可以通过查看ButtonModel接口中的特征来了解按钮模型所维护的数据类别。

表9-1列出了这些特征。
每个JButton对象都存储了一-个按钮模型对象,可以用下列方式得到它的引用。
JButton button = new JButton(“Blue”);
ButtonModel model = button.getModel();
在这里插入图片描述
实际上,不必关注按钮状态的零散信息,只有绘制它的视图才对此感兴趣。诸如按钮是否可用这样的重要信息完全可以通过JButton类得到(当然,JButton类也通过向它的模型询问来获得这些信息)。

  下面查看一下ButtonModel接口中不包含的信息。模型不存储按钮标签或者图标。对于一个按钮来说,仅凭模型无法知道它的外观(实际上,在有关单选按钮的9.4.2节中将会看到,这种纯粹的设计会给程序员带来一些麻烦)。

  需要注意的是,同样的模型(即DefaultButtonModel)可用于下压按钮、单选按钮、复选框、甚至是菜单项。当然,这些按钮都有各自不同的视图和控制器。当使用Metal观感时,JButton类用BasicButtonUI类作为其视图;用ButtonUIListener类作为其控制器。通常,每个Swing组件都有一个相关的后缀为UI的视图对象,但并不是所有的Swing组件都有专门的控制器对象。

  在阅读JButton底层工作的简介之后可能会想到: JButton 究竟是什么?事实上,它仅仅是一个继承了JComponent的包装器类,JComponent 包含了一个DefaultButtonModel对象,一些视图数据(例如按钮标签和图标)和-一个负责按钮视图的BasicButtonUI对象。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值