




已阅读5页,还剩115页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
12JIVE与设计模式JIVE论坛系统使用大量设计模式巧妙地实现了一系列功能。因为设计模式的通用性和可理解性,将帮助更多人很快地理解JIVE论坛源码,从而可以依据一种“协定”来动态地扩展它。那么使用设计模式还有哪些好处21设计模式设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的。设计模式使代码编制真正工程化,设计模式是软件工程的基石。GOF(设计模式作者简称)设计模式这本书第一次将设计模式提升到理论高度,并将之规范化,该书提出了23种基本设计模式。自此,在可复用面向对象软件的发展过程中,新的大量的设计模式不断出现。很多人都知道JAVA是完全面向对象的设计和编程语言,但是由于接受教育以及经验的原因,大多数程序员或设计人员都是从传统的过程语言转变而来,因此在思维习惯上要完全转变为面向对象的设计和开发方式是困难的,而学习设计模式可以更好地帮助和坚固这种转变。凡是学习完成设计模式的人都有一种类似重生的感觉,这种重生可以从很多方面去解释。换一种新的角度来看待和解决问题应该是一种比较贴切的解释,而这种新的思维角度培养属于基础培训,因此,设计模式是学习JAVA的必读基础课程之一。由于设计模式概念比较抽象,对于初学者学习有一定的难度,因此结合JIVE论坛系统学习设计模式将是一种很好的选择。掌握了设计模式,将会帮助程序员或设计人员以更加可重用性、可伸缩性的眼光来开发应用系统,甚至开发通用的框架系统。框架系统是构成一类特定软件可复用设计的一组相互协作的类,主要是对应用系统中反复重用部分的提炼,类似一种模板,这是一种结构性的模板。框架通常定义了应用体系的整体结构、类和对象的关系等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节。框架强调设计复用,而设计模式最小的可重用单位,因此框架不可避免地会反复使用到设计模式。关于通用框架系统的设计开发将在以后章节中讨论。其实JIVE论坛本身也形成了一个基于WEB结构的通用框架系统,因为它很多设计思想是可以重用的,例如设定一个总体入口,通过入口检查用户的访问控制2权限,当然还有其他各方面的功能实现方式都是值得在其他系统中借鉴的,也正因为它以模式的形式表现出来,这种可重用性和可借鉴性就更强。22FORUMFACTORY与工厂模式工厂模式是GOF设计模式的主要常用模式,它主要是为创建对象提供了一种接口,工厂模式主要是封装了创建对象的细节过程,从而使得外界调用一个对象时,根本无需关心这个对象是如何产生的。在GOF设计模式中,工厂模式分为工厂方法模式和抽象工厂模式。两者主要区别是,工厂方法是创建一种产品接口下的产品对象,而抽象工厂模式是创建多种产品接口下的产品对象,非常类似BUILDER生成器模式。在平时实践中,使用较多的基本是工厂方法模式。以类SAMPLEONE为例,要创建SAMPLEONE的对象实例SAMPLEONESAMPLEONENEWSAMPLEONE如果SAMPLE类有几个相近的类SAMPLETWO或SAMPLETHREE,那么创建它们的实例分别是SAMPLETWOSAMPLETWONEWSAMPLETWOSAMPLETHREESAMPLETHREENEWSAMPLETHREE其实这3个类都有一些共同的特征,如网上商店中销售书籍、玩具或者化妆品。虽然它们是不同的具体产品,但是它们有一个共同特征,可以抽象为“商品”。日常生活中很多东西都可以这样高度抽象成一种接口形式。上面这3个类如果可以抽象为一个统一接口SAMPLEIF,那么上面语句就可以成为SAMPLEIFSAMPLEONENEWSAMPLEONESAMPLEIFSAMPLETWONEWSAMPLETWOSAMPLEIFSAMPLETHREENEWSAMPLETHREE在实际情况中,有时并不需要同时生成3种对象,而是根据情况在3者之中选一个。在这种情况下,需要使用工厂方法来完成了,创建一个叫SAMPLEFACTORY的抽象类PUBLICCLASSSAMPLEFACTORYPUBLICABSTRACTSAMPLEIFCREATOR3在这个抽象工厂类中有一个抽象方法CREATOR,但是没有具体实现,而是延迟到它的子类中实现,创建子类SAMPLEFACTORYIMPPUBLICCLASSSAMPLEFACTORYIMPEXTENDSSAMPLEFACTORYPUBLICSAMPLEIFCREATOR/根据其他因素综合判断返回具体产品/假设应该返回SAMPLEONE对象RETURNNEWSAMPLEONE在SAMPLEFACTORYIMP中根据具体情况来选择返回SAMPLEONE、SAMPLETWO或SAMPLETHREE。所谓具体情况有很多种上下文其他过程计算结果;直接根据配置文件中配置。上述工厂方法模式中涉及到一个抽象产品接口SAMPLE,如果还有其他完全不同的产品接口,如PRODUCT等,一个子类SAMPLEFACTORYIMP只能实现一套系列产品方案的生产,如果还需要另外一套系统产品方案,就可能需要另外一个子类SAMPLEFACTORYIMPTWO来实现。这样,多个产品系列、多个工厂方法就形成了抽象工厂模式。前面已经讨论在JIVE中设置了论坛统一入口,这个统一入口就是FORUMFACTORY,以下是FORUMFACTORY的主要代码PUBLICABSTRACTCLASSFORUMFACTORYPRIVATESTATICOBJECTINITLOCKNEWOBJECTPRIVATESTATICSTRINGCLASSNAME“COMYASNAFORUMDATABASEDBFORUMFACTORY“PRIVATESTATICFORUMFACTORYFACTORYNULLPUBLICSTATICFORUMFACTORYGETINSTANCEAUTHORIZATIONAUTHORIZATIONIFAUTHORIZATIONNULL4RETURNNULL/以下使用了SINGLETON单态模式,将在23节讨论IFFACTORYNULLSYNCHRONIZEDINITLOCKIFFACTORYNULL/从配置文件中获得当前CLASSNAMETRY/动态装载类CLASSCCLASSFORNAMECLASSNAMEFACTORYFORUMFACTORYCNEWINSTANCECATCHEXCEPTIONERETURNNULL/返回PROXY用来限制授权对FORUM的访问RETURNNEWFORUMFACTORYPROXYAUTHORIZATION,FACTORY,FACTORYGETPERMISSIONSAUTHORIZATION/创键产品接口FORUM的具体对象实例PUBLICABSTRACTFORUMCREATEFORUMSTRINGNAME,STRINGDESCRIPTION5THROWSUNAUTHORIZEDEXCEPTION,FORUMALREADYEXISTSEXCEPTION/创键产品接口FORUMTHREAD的具体对象实例PUBLICABSTRACTFORUMTHREADCREATETHREADFORUMMESSAGEROOTMESSAGETHROWSUNAUTHORIZEDEXCEPTION/创键产品接口FORUMMESSAGE的具体对象实例PUBLICABSTRACTFORUMMESSAGECREATEMESSAGEFORUMFACTORY中提供了很多抽象方法如CREATEFORUM、CREATETHREAD和CREATEMESSAGE等,它们是创建各自产品接口下的具体对象,这3个接口就是前面分析的基本业务对象FORUM、FORUMTHREAD和FORUMMESSAGE,这些创建方法在FORUMFACTORY中却不立即执行,而是推迟到FORUMFACTORY子类中实现。FORUMFACTORY的子类实现是COMYASNAFORUMDATABASEDBFORUMFACTORY,这是一种数据库实现方式。即在DBFORUMFACTORY中分别实现了在数据库中CREATEFORUM、CREATETHREAD和CREATEMESSAGE等3种方法,当然也提供了动态扩展到另外一套系列产品的生产方案的可能。如果使用XML来实现,那么可以编制一个XMLFORUMFACTORY的具体工厂子类来分别实现3种创建方法。因此,JIVE论坛在统一入口处使用了抽象工厂模式来动态地创建论坛中所需要的各种产品,如图34所示。6图34FORUMFACTORY抽象工厂模式图图34中,XMLFORUMFACTORY和DBFORUMFACTORY作为抽象工厂FORUMFACTORY的两个具体实现,而FORUM、FORUMTHREAD和FORUMMESSAGE分别作为3个系列抽象产品接口,依靠不同的工厂实现方式,会产生不同的产品对象。从抽象工厂模式去理解JIVE论坛统一入口处,可以一步到位掌握了几个类之间的大概关系。因为使用了抽象工厂模式这种通用的设计模式,可以方便源码阅读者快速地掌握整个系统的结构和来龙去脉,图34这张图已经初步展示了JIVE的主要框架结构。细心的读者也许会发现,在上面FORUMFACTORY有一个GETINSTANCE比较令人费解,这将在23节进行讨论。723统一入口与单态模式在上面FORUMFACTORY的GETINSTANCE方法使用单态(SINGLETON)模式。单态模式是保证一个类有且仅有一个对象实例,并提供一个访问它的全局访问点。前面曾提到FORUMFACTORY是JIVE提供客户端访问数据库系统的统一入口。为了保证所有的客户端请求都要经过这个FORUMFACTORY,如果不使用单态模式,客户端下列调用语句表示生成了FORUMFACTORY实例FORUMFACTORYFACTORYNEWDBFORUMFACTORY客户端每发生一次请求都调用这条语句,这就会发生每次都生成不同FACTORY对象实例,这显然不符合设计要求,因此必须使用单态模式。一般在JAVA实现单态模式有几种选择,最常用而且安全的用法如下PUBLICCLASSSINGLETONPRIVATESINGLETON/在自己内部定义自己一个实例,是不是很奇怪/注意这是PRIVATE,只供内部调用PRIVATESTATICSINGLETONINSTANCENEWSINGLETON/这里提供了一个供外部访问本CLASS的静态方法,可以直接访问PUBLICSTATICSINGLETONGETINSTANCERETURNINSTANCE单态模式一共使用了两条语句实现第一条直接生成自己的对象,第二条提供一个方法供外部调用这个对象,同时最好将构造函数设置为PRIVATE,以防止其他程序员直接使用NEWSINGLETON生成实例。还有一种JAVA单态模式实现PUBLICCLASSSINGLETONPRIVATESINGLETON8PRIVATESTATICSINGLETONINSTANCENULLPUBLICSTATICSYNCHRONIZEDSINGLETONGETINSTANCEIFINSTANCENULLINSTANCENEWSINGLETONRETURNINSTANCE在上面代码中,使用了判断语句。如果INSTANCE为空,再进行实例化,这成为LAZYINITIALIZATION。注意GETINSTANCE方法的SYNCHRONIZED,这个SYNCHRONIZED很重要。如果没有SYNCHRONIZED,那么使用GETINSTANCE在第一次被访问时有可能得到多个SINGLETON实例。关于LAZYINITIALIZATION的SINGLETON有很多涉及DOUBLECHECKEDLOCKINGDCL的讨论,有兴趣者可以进一步研究。一般认为第一种形式要更加安全些;但是后者可以用在类初始化时需要参数输入的情况下。在JIVE的FORUMFACTORY中采取了后者LAZYINITIALIZATION形式,这是为了能够动态配置指定FORUMFACTORY的具体子类。在GETINSTANCE中,从配置文件中获得当前工厂的具体实现,如果需要启动XMLFORUMFACTORY,就不必修改FORUMFACTORY代码,直接在配置文件中指定CLASSNAME的名字为XMLFORUMFACTORY。这样通过下列动态装载机制生成FORUMFACTORY具体对象CLASSCCLASSFORNAMECLASSNAMEFACTORYFORUMFACTORYCNEWINSTANCE这是利用JAVA的反射机制,可以通过动态指定CLASSNAME的数值而达到生成对象的方式。使用单态模式的目标是为了控制对象的创建,单态模式经常使用在控制资源的访问上。例如数据库连接或SOCKET连接等。单态模式可以控制在某个时刻只有一个线程访问资源。由于JAVA中没有全局变量的概念,因此使用单态模式有时可以起到这种作用,当然需要注意是在一个JVM中。24访问控制与代理模式仔细研究会发现,在FORUMFACTORY的GETINSTANCE方法中最后的返回值有些奇怪。按照单态模式的概念应该直接返回FACTORY这个对象实例,但是却返回了9FORUMFACTORYPROXY的一个实例,这实际上改变了单态模式的初衷。这样客户端每次通过调用FORUMFACTORY的GETINSTANCE返回的就不是FORUMFACTORY的惟一实例,而是新的对象。之所以这样做是为了访问权限的控制,姑且不论这样做的优劣,先看看什么是代理模式。代理模式是属于设计模式结构型模式中一种,它是实际访问对象的代理对象,或者影子对象,主要达到控制实际对象的访问。这种控制的目的很多,例如提高性能等。即远程代理模式,这种模式将在以后章节讨论。其中一个主要的控制目的是控制客户端对实际对象的访问权限。在JIVE系统中,因为有角色权限的分别,对于FORUM、FORUMTHREAD和FROUMMESSAGE的访问操作必须经过权限机制验证后才能进行。以FORUMFACTORYPROXY中的CREATEFORUM方法为例,其实FORUMFACTORYPROXY也是FROUMFACTORY的一种工厂实现,它的CREATEFORUM具体实现如下PUBLICFORUMCREATEFORUMSTRINGNAME,STRINGDESCRIPTIONTHROWSUNAUTHORIZEDEXCEPTION,FORUMALREADYEXISTSEXCEPTIONIFPERMISSIONSGETFORUMPERMISSIONSSYSTEM_ADMINFORUMNEWFORUMFACTORYCREATEFORUMNAME,DESCRIPTIONRETURNNEWFORUMPROXYNEWFORUM,AUTHORIZATION,PERMISSIONSELSETHROWNEWUNAUTHORIZEDEXCEPTION在这个方法中进行了权限验证,判断是否属于系统管理员。如果是,将直接从DBFORUMFACTORY对象FACTORY的方法CREATEFORUM中获得一个新的FORUM对象,然后再返回FORUM的子类代理对象FORUMPROXY。因为在FORUM中也还有很多属性和操作方法,这些也需要进行权限验证。FORUMPROXY和FORUMFACTORYPROXY起到类似的作用。JIVE中有下列几个代理类10FORUMFACTORYPROXY客户端和DBFORUMFACTORY之间的代理。客户端访问DBFORUMFACTORY的任何方法都要先经过FORUMFACTORYPROXY相应方法代理一次。以下意思相同。FORUMPROXY客户端和DBFORUM之间的代理,研究FORUM对象的每个方法,必须先看FORUMPROXY对象的方法。FORUMMESSAGEPROXY客户端和DBFORUMMESSAGE之间的代理。FORUMTHREADPROXY客户端和DBFORUMTHREAD之间的代理。USER和GROUP也有相应的代理类。由以上分析看出,每个数据对象都有一个代理。如果系统中数据对象非常多,依据这种一对一的代理关系,会有很多代理类,将使系统变得不是非常干净,因此可以使用动态代理来代替这所有的代理类,具体实现将在以后章节讨论。25批量分页查询与迭代模式迭代(ITERATOR)模式是提供一种顺序访问某个集合各个元素的方法,确保不暴露该集合的内部表现。迭代模式应用于对大量数据的访问,JAVACOLLECTIONAPI中ITERATOR就是迭代模式的一种实现。在前面章节已经讨论过,用户查询大量数据,从数据库不应该直接返回RESULTSET,应该是COLLECTION。但是有一个问题,如果这个数据很大,需要分页面显示。如果一下子将所有页面要显示的数据都查询出来放在COLLECTION,会影响性能。而使用迭代模式则不必将全部集合都展现出来,只有遍历到某个元素时才会查询数据库获得这个元素的数据。以论坛中显示帖子主题为例,在一个页面中不可能显示所有主题,只有分页面显示,如图35所示。图35中一共分15页来显示所有论坛帖子,可以从显示FORUMJSP中发现下列语句可以完成上述结果RESULTFILTERFILTERNEWRESULTFILTER/设置结果过滤器FILTERSETSTARTINDEXSTART/设置开始点FILTERSETNUMRESULTSRANGE/设置范围11FORUMTHREADITERATORTHREADSFORUMTHREADSFILTER/获得迭代器WHILETHREADSHASNEXT/逐个显示THREADS中帖子主题,输出图35中的每一行图35分页显示所有帖子上述代码中主要是从FORUM的THREADS方法获得迭代器FORUMTHREADITERATOR的实例,依据前面代理模式中分析、研究FORUM对象的方法,首先是看FORUMPROXY中对应方法,然后再看DBFORUM中对应方法的具体实现。在FORUMPROXY中,THREADS方法如下PUBLICFORUMTHREADITERATORTHREADSRESULTFILTERRESULTFILTERFORUMTHREADITERATORITERATORFORUMTHREADSRESULTFILTERRETURNNEWFORUMTHREADITERATORPROXYITERATOR,AUTHORIZATION,PERMISSIONS首先是调用了DBFORUM中具体的THREADS方法,再追踪到DBFORUM中看看,它的THREADS方法代码如下PUBLICFORUMTHREADITERATORTHREADSRESULTFILTERRESULTFILTER/按RESULTFILTER设置范围要求获得SQL查询语句STRINGQUERYGETTHREADLISTSQLRESULTFILTER,FALSE/获得RESULTFILTER设置范围内的所有THREADID集合LONGTHREADBLOCKGETTHREADBLOCKQUERYTOSTRING,RESULTFILTERGETSTARTINDEX12/以下是计算查询区域的开始点和终点INTSTARTINDEXRESULTFILTERGETSTARTINDEXINTENDINDEX/IFNUMBEROFRESULTSISSETTOINIFINITE,SETENDINDEXTOTHETOTAL/NUMBEROFTHREADSINTHEFORUMIFRESULTFILTERGETNUMRESULTSRESULTFILTERNULL_INTENDINDEXINTGETTHREADCOUNTRESULTFILTERELSEENDINDEXRESULTFILTERGETNUMRESULTSSTARTINDEXRETURNNEWFORUMTHREADBLOCKITERATORTHREADBLOCK,QUERYTOSTRING,STARTINDEX,ENDINDEX,THISID,FACTORYRESULTFILTER是一个查询结果类,可以对论坛主题THREAD和帖子内容MESSAGE进行过滤或排序,这样就可以根据用户要求定制特殊的查询范围。如查询某个用户去年在这个论坛发表的所有帖子,那只要创建一个RESULTFILTER对象就可以代表这个查询要求。在上面THREADS方法代码中,第一步是先定制出相应的动态SQL查询语句,然后使用这个查询语句查询数据库,获得查询范围内所有的FORUMTHREAD的ID集合,然后在这个ID集合中获得当前页面的ID子集合,这是非常关键的一步。在这关键的一步中,有两个重要的方法GETTHREADLISTSQL和GETTHREADBLOCKGETTHREADLISTSQL获得SQL查询语句QUERY的值,这个方法JIVE实现起来显得非常地琐碎。13GETTHREADBLOCK获得当前页面的ID子集合,那么如何确定ID子集合的开始位置呢查看GETTHREADBLOCK方法代码,可以发现,它是使用最普遍的RESULTSETNEXT方法来逐个跳跃到开始位置。上面代码的THREADS方法中最后返回的是FORUMTHREADBLOCKITERATOR,它是抽象类FORUMTHREADITERATOR的子类,而FORUMTHREADITERATOR继承了COLLECTION的ITERATOR,以此声明自己是一个迭代器,FORUMMESSAGEBLOCKITERATOR实现的具体方法如下PUBLICBOOLEANHASNEXT/判断是否有下一个元素PUBLICBOOLEANHASPREVIOUS/判断是否有前一个元素PUBLICOBJECTNEXTTHROWSJAVAUTILNOSUCHELEMENTEXCEPTION/获得下一个元素实例FORUMTHREADBLOCKITERATOR中的BLOCK是“页”的意思,它的一个主要类变量THREADBLOCK包含的是一个页面中所有FORUMTHREAD的ID,NEXT方法实际是对THREADBLOCK中FORUMTHREAD进行遍历,如果这个页面全部遍历完成,将再获取下一页(BLOCK)数据。在FORUMTHREADBLOCKITERATOR重要方法GETELEMENT中实现了两个功能如果当前遍历指针超过当前页面,将使用GETTHREADBLOCK获得下一个页面的ID子集合;如果当前遍历指针在当前页面之内,根据ID获得完整的数据对象,实现输出;FORUMTHREADBLOCKITERATOR的GETELEMENT方法代码如下PRIVATEOBJECTGETELEMENTINTINDEXIFINDEXBLOCKSTARTDBFORUMTHREAD_BLOCK_SIZETRY/从缓冲中获得FORUM实例14DBFORUMFORUMFACTORYCACHEMANAGERFORUMCACHEGETFORUMID/获得下一页的内容THISTHREADBLOCKFORUMGETTHREADBLOCKQUERY,INDEXTHISBLOCKIDINDEX/DBFORUMTHREAD_BLOCK_SIZETHISBLOCKSTARTBLOCKIDDBFORUMTHREAD_BLOCK_SIZECATCHFORUMNOTFOUNDEXCEPTIONFNFERETURNNULLOBJECTELEMENTNULL/计算这个元素在当前查询范围内的相对位置INTRELATIVEINDEXINDEXDBFORUMTHREAD_BLOCK_SIZE/MAKESUREINDEXISNTTOOLARGEIFRELATIVEINDEXTHREADBLOCKLENGTHTRY/从缓冲中获得实际THREAD对象ELEMENTFACTORYCACHEMANAGERTHREADCACHEGETTHREADBLOCKRELATIVEINDEXCATCHFORUMTHREADNOTFOUNDEXCEPTIONTNFERETURNELEMENT15FORUMTHREADBLOCKITERATOR是真正实现分页查询的核心功能,FORUMTHREADBLOCKITERATOR对象返回到客户端的过程中,遭遇FORUMTHREADITERATORPROXY的截获,可以回头看看FORUMPROXY中的THREADS方法,它最终返回给调用客户端FORUMJSP的是FORUMTHREADITERATORPROXY实例。FORUMTHREADITERATORPROXY也是迭代器FORUMTHREADITERATOR的一个子类,它的一个具体方法中PUBLICOBJECTNEXTRETURNNEWFORUMTHREADPROXYFORUMTHREADITERATORNEXT,AUTHORIZATION,PERMISSIONS这一句是返回一个FORUMTHREADPROXY实例,返回就是一个FORUMTHREAD实例的代理。这里,JIVE使用代理模式实现访问控制实现得不是很巧妙,似乎有代理到处“飞”的感觉,这是可以对之进行改造的。从以上可以看出,JIVE在输出如图35所示的多页查询结果时,采取了下列步骤(1)先查询出符合查询条件的所有对象元素的ID集合,注意不是所有对象元素,只是其ID的集合,这样节约了大量内存。(2)每个页面视为一个BLOCK,每当进入下一页时,获得下一个页面的所有对象的ID集合。(3)输出当前页面的所有对象时,首先从缓冲中获取,如果缓冲中没有,再根据ID从数据库中获取完整的对象数据。上述实现方法完全基于即查即显,相比于一般批量查询做法一次性获得所有数据,然后遍历数据结果集RESULTSET,JIVE这种批量查询方式是一种比较理想的选择。以上是FORUMTHREAD的批量显示,有关帖子内容FORUMMESSAGE也是采取类似做法。在每个FORUMTHREAD中可能有很多帖子内容(FORUMMESSAGE对象集合),也不能在一个页面中全部显示,所以也是使用迭代模式来实现的。显示一个FORUM主题下所有帖子内容的功能由FORUMTHREAD的MESSAGES方法完成,检查它的代理类FROUMTHREADPROXY如何具体完成PUBLICITERATORMESSAGESRESULTFILTERRESULTFILTER16ITERATORITERATORTHREADMESSAGESRESULTFILTERRETURNNEWITERATORPROXYJIVEGLOBALSMESSAGE,ITERATOR,AUTHORIZATION,PERMISSIONS实现的原理基本相同,返回的都是一个ITERATOR代理类,在这些代理类中都是进行用户权限检验的。JIVE中也有关于一次性获得所有数据,然后遍历RESULTSET的做法。这种做法主要适合一次性查询数据库的所有数据,例如查询当前所有论坛FORUM,首先实现SQL语句SELECTFORUMIDFROMJIVEFORUM获得所有FORUM的FORUMID,这段代码位于DBFORUMFACTORYJAVA的FORUMS方法中,如下PUBLICITERATORFORUMSIFFORUMSNULLLONGLISTFORUMLISTNEWLONGLISTCONNECTIONCONNULLPREPAREDSTATEMENTPSTMTNULLTRYCONCONNECTIONMANAGERGETCONNECTION/GET_FORUMS值是SELECTFORUMIDFROMJIVEFORUMPSTMTCONPREPARESTATEMENTGET_FORUMSRESULTSETRSPSTMTEXECUTEQUERYWHILERSNEXTFORUMLISTADDRSGETLONG1/将所有查询ID结果放入FORUMLIST中17CATCHSQLEXCEPTIONSQLESQLEPRINTSTACKTRACEFINALLYRETURNNEWDATABASEOBJECTITERATORJIVEGLOBALSFORUM,FORUMS,THISFORUMS方法是返回一个DATABASEOBJECTITERATOR,这个DATABASEOBJECTITERATOR也是一个迭代器,但是实现原理要比FORUMTHREADBLOCKITERATOR简单。它只提供了一个遍历指针,在所有ID结果集中遍历,然后也是通过ID获得完整的数据对象。总之,JIVE中关于批量查询有两种实现方式以FORUMTHREADBLOCKITERATOR为代表的实现方式适合在数据量巨大、需要多页查询时使用;而DATABASEOBJECTITERATOR则是推荐在一个页面中显示少量数据时使用。26过滤器与装饰模式装饰(DECORATOR)模式是动态给一个对象添加一些额外的职责,或者说改变这个对象的一些行为。这就类似于使用油漆为某个东西刷上油漆,在原来的对象表面增加了一层外衣。在装饰模式中,有两个主要角色一个是被刷油漆的对象(DECORATEE);另外一个是给DECORATEE刷油漆的对象(DECORATOR)。这两个对象都继承同一个接口。首先举一个简单例子来说明什么是装饰模式。先创建一个接口PUBLICINTERFACEWORKPUBLICVOIDINSERT18这是一种打桩工作的抽象接口,动作INSERT表示插入,那么插入什么下面这个实现表示方形木桩的插入PUBLICCLASSSQUAREPEGIMPLEMENTSWORKPUBLICVOIDINSERTSYSTEMOUTPRINTLN“方形桩插入“本来这样也许就可以满足打桩的工作需要,但是有可能土质很硬,在插入方形桩之前先要打一个洞,那么又将如何实现可以编制一个DECORATOR类,同样继承WORK接口,但是在实现INSERT方法时有些特别PUBLICCLASSDECORATORIMPLEMENTSWORKPRIVATEWORKWORK/额外增加的功能被打包在这个LIST中PRIVATEARRAYLISTOTHERSNEWARRAYLISTPUBLICDECORATORWORKWORKTHISWORKWORKOTHERSADD“打洞“/准备好额外的功能PUBLICVOIDINSERTOTHERMETHODWORKINSERTPUBLICVOIDOTHERMETHOD19LISTITERATORLISTITERATOROTHERSLISTITERATORWHILELISTITERATORHASNEXTSYSTEMOUTPRINTLNSTRINGLISTITERATORNEXT“正在进行“在DECORATOR的方法INSERT中先执行OTHERMETHOD方法,然后才实现SQUAREPEG的INSERT方法。油漆工DECORATOR给被油漆者SQUAREPEG添加了新的行为打洞。具体客户端调用如下WORKSQUAREPEGNEWSQUAREPEGWORKDECORATORNEWDECORATORSQUAREPEGDECORATORINSERT本例中只添加了一个新的行为(打洞),如果还有很多类似的行为,那么使用装饰模式的优点就体现出来了。因为可以通过另外一个角度(如组织新的油漆工实现子类)来对这些行为进行混合和匹配,这样就不必为每个行为创建一个类,从而减少了系统的复杂性。使用装饰模式可以避免在被油漆对象DECORATEE中包装很多动态的,可能需要也可能不需要的功能,只要在系统真正运行时,通过油漆工DECORATOR来检查那些需要加载的功能,实行动态加载。JIVE论坛实现了信息过滤功能。例如可以将帖子内容中的HTML语句过滤掉;可以将帖子内容中JAVA代码以特别格式显示等。这些过滤功能有很多,在实际使用时不一定都需要,是由实际情况选择的。例如有的论坛就不需要将帖子内容的HTML语句过滤掉,选择哪些过滤功能是由论坛管理者具体动态决定的。而且新的过滤功能可能随时可以定制开发出来,如果试图强行建立一种接口包含所有过滤行为,那么到时有新过滤功能加入时,还需要改变接口代码,真是一种危险的行为。装饰模式可以解决这种运行时需要动态增加功能的问题,且看看JIVE是如何实现的。20前面讨论过,在JIVE中,有主要几个对象FORUMFACTORY、FORUM以及FORUMTHREAD和FORUMMESSAGE,它们之间的关系如图32所示。因此帖子内容FORUMMESSAGE对象的获得是从其上级FROUMTHREAD的方法GETMESSAGE中获取,但是在实际代码中,FORUMTHREAD的方法GETMESSAGE委托FORUMFACTORY来获取FORUMMESSAGE对象。看看FORUMTHREAD的子类DBFORUMTHREAD的GETMESSAGE代码PUBLICFORUMMESSAGEGETMESSAGELONGMESSAGEIDTHROWSFORUMMESSAGENOTFOUNDEXCEPTIONRETURNFACTORYGETMESSAGEMESSAGEID,THISID,FORUMID这是一种奇怪的委托,大概是因为需要考虑到过滤器功能有意为之吧。那就看看FORUMFACTORY的具体实现子类DBFORUMFACTORY的GETMESSAGE功能,GETMESSAGE是将数据库中的FORUMMESSAGE对象经由过滤器过滤一遍后输出(注因为原来的JIVE的GETMESSAGE代码考虑到可缓存或不可缓存的过滤,比较复杂,实际过滤功能都是可以缓存的,因此精简如下)。PROTECTEDFORUMMESSAGEGETMESSAGELONGMESSAGEID,LONGTHREADID,LONGFORUMIDTHROWSFORUMMESSAGENOTFOUNDEXCEPTIONDBFORUMMESSAGEMESSAGECACHEMANAGERMESSAGECACHEGETMESSAGEID/DOASECURITYCHECKTOMAKESURETHEMESSAGECOMESFROMTHETHREADIFMESSAGETHREADIDTHREADIDTHROWNEWFORUMMESSAGENOTFOUNDEXCEPTIONFORUMMESSAGEFILTERMESSAGENULLTRY21/应用全局过滤器FILTERMESSAGEFILTERMANAGERAPPLYFILTERSMESSAGEFORUMFORUMGETFORUMFORUMID/应用本论坛过滤器FILTERMESSAGEFORUMGETFILTERMANAGERAPPLYFILTERSFILTERMESSAGECATCHEXCEPTIONERETURNFILTERMESSAGE上面代码实际是装饰模式的客户端调用代码,DBFORUMMESSAGE的实例MESSAGE是被油漆者DECORATEE。通过FILTERMANAGER或FORUMGETFILTERMANAGER的APPLYFILTER方法,将MESSAGE实行了所有的过滤功能。这就类似前面示例的下列语句WORKDECORATORNEWDECORATORSQUAREPEGFORUMGETFILTERMANAGER是从数据库中获取当前配置的所有过滤器类。每个FORUM都有一套自己的过滤器类,这是通过下列语句实现的FILTERMANAGERFILTERMANAGERNEWDBFILTERMANAGER在DBFILTERMANAGER的类变量FORUMMESSAGEFILTERFILTERS中保存着所有的过滤器,APPLYFILTERS方法实行过滤如下PUBLICFORUMMESSAGEAPPLYFILTERSFORUMMESSAGEMESSAGEFORINTI0IFILTERSLENGTHIIFFILTERSINULLMESSAGEFILTERSICLONEMESSAGE22RETURNMESSAGE而FORUMMESSAGEFILTER是FORUMMESSAGE的另外一个子类,被油漆者DBFORUMMESSAGE通过油漆工FORUMMESSAGEFILTER增加了一些新的行为和功能(过滤),如图36所示。图36装饰模式这就组成了一个稍微复杂一点的装饰模式。HTMLFILTER实现了HTML代码过滤功能,而JAVACODEHIGHLIGHTER实现了JAVA代码过滤功能,HTMLFILTER代码如下PUBLICCLASSHTMLFILTEREXTENDSFORUMMESSAGEFILTERPUBLICFORUMMESSAGEFILTERCLONEFORUMMESSAGEMESSAGEHTMLFILTERFILTERNEWHTMLFILTERFILTERMESSAGEMESSAGERETURNFILTERPUBLICBOOLEANISCACHEABLERETURNTRUEPUBLICSTRINGGETSUBJECTRETURNSTRINGUTILSESCAPEHTMLTAGSMESSAGEGETSUBJECT23PUBLICSTRINGGETBODYRETURNSTRINGUTILSESCAPEHTMLTAGSMESSAGEGETBODYHTMLFILTER中重载了FORUMMESSAGE的GETSUBJECT、GETBODY方法,实际是改变了这两个原来的行为,这类似前面举例的方法PUBLICVOIDINSERTOTHERMETHODWORKINSERT这两者都改变了被油漆者的行为。在HTMLFILTER中还使用了原型(PROTOTYPE)模式,原型模式定义是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。按照这种定义,JAVA的CLONE技术应该是原型模式的一个实现。HTMLFILTER的CLONE方法实际就是在当前HTMLFILTER实例中再生成一个同样的实例。这样在处理多个并发请求时,不用通过同一个过滤器实例进行处理,提高了性能。但是HTMLFILTER的CLONE方法是采取NEW方法来实现,不如直接使用OBJECT的NATIVE方法速度快。因为在DBFILTERMANAGER中是根据配置使用类反射机制动态分别生成包括HTMLFILTER在内的过滤器实例。但是每种过滤器实例只有一个,为了使得大量用户不必争夺一个过滤器实例来实现过滤,就采取了克隆方式,这种实战手法可以借鉴在自己的应用系统中。27主题监测与观察者模式观察者(OBSERVER)模式是定义对象之间一对多的依赖关系,当一个被观察的对象发生改变时,所有依赖于它的对象都会得到通知并采取相应行为。使用观察者模式的优点是将被观察者和观察者解耦,从而可以不影响被观察者继续自己的行为动作。观察者模式适合应用于一些“事件触发”场合。24在JIVE中,用户也许会对某个主题感兴趣,希望关于此主题发生的任何新的讨论能通过电子邮件通知他,因此他订阅监视了这个主题。因为这个功能的实现会引入电子邮件的发送。在前面章节已经讨论了电子邮件发送有可能因为网络原因延迟,如果在有人回复这个主题时,立即进行电子邮件发送,通知所有订阅该主题的用户。那么该用户可能等待很长时间得不到正常回应。使用观察者模式,可以通过触发一个观察者,由观察者通过另外线程来实施邮件发送,而被观察者发出触发通知后,可以继续自己原来的逻辑行为。看看JIVE的WATCHMANAGER类PUBLICINTERFACEWATCHMANAGER/正常监察类型,用户在这个主题更新后再次访问时,会明显地发现PUBLICSTATICFINALINTNORMAL_WATCH0/当主题变化时,通过电子邮件通知用户PUBLICSTATICFINALINTEMAIL_NOTIFY_WATCH1/设置一个主题被观察的时间,默认为30天PUBLICVOIDSETDELETEDAYSINTDELETEDAYSTHROWSUNAUTHORIZEDEXCEPTIONPUBLICINTGETDELETEDAYS/是否激活了EMAIL提醒PUBLICBOOLEANISEMAILNOTIFYENABLEDTHROWSUNAUTHORIZEDEXCEPTIONPUBLICVOIDSETEMAILNOTIFYENABLEDBOOLEANENABLEDTHROWSUNAUTHORIZEDEXCEPTION/保存EMAIL的内容PUBLICSTRINGGETEMAILBODYTHROWSUNAUTHORIZEDEXCEPTIONPUBLICVOIDSETEMAILBODYSTRINGBODYTHROWSUNAUTHORIZEDEXCEPTION/保存EMAIL的主题PUBLICSTRINGGETEMAILSUBJECTTHROWSUNAUTHORIZEDEXCEPTION25PUBLICVOIDSETEMAILSUBJECTSTRINGSUBJECTTHROWSUNAUTHORIZEDEXCEPTION/为某个主题创建一个观察者PUBLICVOIDCREATEWATCHUSERUSER,FORUMTHREADTHREAD,INTWATCHTYPETHROWSUNAUTHORIZEDEXCEPTION/删除某个主题的观察者PUBLICVOIDDELETEWATCHUSERUSER,FORUMTHREADTHREAD,INTWATCHTYPE/得到一个主题的所有观察者PUBLICITERATORGETWATCHEDFORUMTHREADSUSERUSER,INTWATCHTYPETHROWSUNAUTHORIZEDEXCEPTION/判断一个用户是否在观察监视该主题PUBLICBOOLEANISWATCHEDTHREADUSERUSER,FORUMTHREADTHREAD,INTWATCHTYPETHROWSUNAUTHORIZEDEXCEPTIONDBWATCHMANAGER是WATCHMANAGER的一个子类,通过数据库保存着有关某个主题被哪些用户监视等数据资料。WATCHMANAGER对象是随同DBFORUMFACTORY一起生成的。在DBWATCHMANAGER中有一个WATCHMANAGER没有的很重要的方法通知方法PROTECTEDVOIDNOTIFYWATCHESFORUMTHREADTHREAD/IFWATCHESARETURNEDON26IFEMAILNOTIFYENABLEDRETURN/通知所有观察这个主题的用户EMAILWATCHUPDATETASKTASKNEWEMAILWATCHUPDATETASKTHIS,FACTORY,THREADTASKENGINEADDTASKTASK这个方法用来触发所有有关这个主题的监视或订阅用户,以EMAIL发送提醒他们。那么这个通知方法
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 会计技能考试题库及答案
- 眼镜学考试题库及答案
- 海南安检证考试题库及答案
- 瑞声科技培训笔试题目及答案
- 人事专员笔试试题及答案
- 国际碳交易视角下森林碳汇市场价格的多维剖析与策略构建
- 2025免疫培训试题及答案
- 地球公转与四季地理基础知识试题及答案
- 涂料清工合同(标准版)
- 音乐旋律创作音乐基础知识试题及答案
- 颈椎骨折课件导图
- 2025至2030中国工业云平台行业发展研究与产业战略规划分析评估报告
- 2025餐饮合伙经营合同协议书
- 2025年山东西学中题库及答案
- 14.2物质的比热容同步练习(含答案) 沪科版物理九年级全一册
- 《国家机构有哪些》课件
- 肉制品安全培训会课件
- 五年级数学口算训练题库及解题技巧
- 江苏省泰州市兴化市昭阳湖初级中学2023-2024学年七年级上学期语文第一次质量抽测试卷(含答案)
- 2024夏季中国东方航空股份有限公司社会招聘笔试模拟试题含答案详解(能力提升)
- 冬季矿山安全生产培训课件
评论
0/150
提交评论