|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
因为能用到多少功能就用多少,不能用就不用!总的来说:要简单要性能好,可以不用框架。你说java复杂,就是因为你把java(j2ee)与这些框架混在了一起。
察看者形式在Swing开辟中很罕见,在GUI使用程序之外的场景中,它对于打消组件的耦合性也十分有效。可是,仍旧存在一些侦听器挂号和挪用方面的罕见缺点。在Java实际与理论的这一期中,Java专家BrianGoetz就怎样做一个好的侦听器,和怎样对您的侦听器也友爱,供应了一些感到很好的倡议。请在响应的会商论坛上与作者和其他读者分享您对这篇文章的设法。(您也能够单击本文顶部或底部的会商会见论坛。)
Swing框架以事务侦听器的情势普遍使用了察看者形式(也称为公布-定阅模式)。Swing组件作为用户交互的方针,在用户与它们交互的时分触发事务;数据模子类在数据产生变更时触发事务。用这类体例利用察看者,可让把持器与模子分别,让模子与视图分别,从而简化GUI使用程序的开辟。
“四人帮”的计划形式一书(参阅参考材料)把察看者形式形貌为:界说对象之间的“一对多”干系,如许一个对象改动形态时,一切它的依附项城市被关照,并主动更新。察看者形式撑持组件之间的松懈耦合;组件能够坚持它们的形态同步,却不必要间接晓得相互的标识或外部情形,从而增进了组件的重用。
AWT和Swing组件(比方JButton或JTable)利用察看者形式打消了GUI事务天生与它们在指定使用程序中的语义之间的耦合。相似地,Swing的模子类,比方TableModel和TreeModel,也利用察看者打消数据模子暗示与视图生成之间的耦合,从而撑持不异数据的多个自力的视图。Swing界说了Event和EventListener对象条理布局;能够天生事务的组件,比方JButton(可视组件)或TableModel(数据模子),供应了addXxxListener()和removeXxxListener()办法,用于侦听器的挂号和作废挂号。这些类卖力决意什么时分它们必要触发事务,甚么时分的确触发事务,和甚么时分挪用一切挂号的侦听器。
为了撑持侦听器,对象必要保护一个已挂号的侦听器列表,供应侦听器挂号和作废挂号的手腕,并在得当的事务产生时挪用每一个侦听器。利用和撑持侦听器很简单(不单单在GUI使用程序中),可是在挂号接口的双方(它们是撑持侦听器的组件和挂号侦听器的组件)都应该制止一些缺点。
线程平安成绩
一般,挪用侦听器的线程与挂号侦听器的线程分歧。要撑持从分歧线程挂号侦听器,那末不论用甚么机制存储和办理举动侦听器列表,这个机制都必需是线程平安的。Sun的文档中的很多示例利用Vector保留侦听器列表,它办理了部分成绩,可是没有办理全体成绩。在事务触发时,触发它的组件会思索迭代侦听器列表,并挪用每一个侦听器,这就带来了并发修正的风险,好比在侦听器列表迭代时代,某个线程偶尔想增加或删除一个侦听器。
办理侦听器列表
假定您利用Vector<Listener>保留侦听器列表。固然Vector类是线程平安的(意味着不必要举行分外的同步便可挪用它的办法,没有损坏Vector数据布局的风险),可是汇合的迭代中包括“检测然后实行”序列,如果在迭代时代汇合被修正,就有了失利的风险。假定迭代入手下手时列表中有三个侦听器。在迭代Vector时,反复挪用size()和get()办法,直到一切元素都检索完,如清单1所示:
清单1.Vector的不平安迭代Vector<Listener>v;
for(inti=0;i<v.size();i++)
v.get(i).eventHappened(event);
可是,假如刚好就在最初一次挪用Vector.size()以后,有人从列表中删除了一个侦听器,会产生甚么呢?如今,Vector.get()将前往null(这是对的,由于从前次检测vector的形态以来,它的形态已变了),而在试图挪用eventHappened()时,会抛出NullPointerException。这是“检测然后实行”序列的一个示例——检测是不是存在更多元素,假如存在,就获得下一元素——可是在存在并发修正的情形下,检测以后形态大概已变更。演示了这个成绩:
.并发迭代和修正,形成料想以外的失利
<br>
这个成绩的一个办理计划是在迭代时代持有对Vector的锁;另外一个计划是克隆Vector或挪用它的toArray()办法,在每次产生事务时检索它的内容。一切这两个办法都有功能上的成绩:第一个的风险是在迭代时代,会把其他想访问侦听器列表的线程锁在表面;第二个则要创立一时对象,并且每次事务产生时都要拷贝列表。
假如用迭代器(Iterator)往遍历侦听器列表,也会有一样的成绩,只是表现略有分歧;iterator()完成不抛出NullPointerException,它在探测到迭代入手下手以后汇合产生修正时,会抛出ConcurrentModificationException。一样,也能够经由过程在迭代时代锁定汇合避免这个成绩。
java.util.concurrent中的CopyOnWriteArrayList类,可以匡助避免这个成绩。它完成了List,并且是线程平安的,可是它的迭代器不会抛出ConcurrentModificationException,遍历时代也不请求分外的锁定。这类特征组合是经由过程在每次列表修正时,在外部从头分派并拷贝列表内容而完成的,如许,遍历内容的线程不必要处置变更——从它们的角度来讲,列表的内容在遍历时代坚持稳定。固然这听起来大概没效力,可是请记着,在多半察看者情形下,每一个组件只要大批侦听器,遍历的数目远远凌驾拔出和删除的数目。以是更快的迭代能够抵偿较慢的变更历程,并供应更好的并发性,由于多个线程能够同时迭代列表。
<p>
恰恰证明了java的简单,要不怎么没有通过c/c++来搞个这种框架? |
|