1、 1 2 Jive与设计模式 Jive 论坛系统使用大量设计模式巧妙地实现了一系列功能。因为设计模式的通用性和可理解性,将帮助更多人很快地理解 Jive 论坛源码,从而可以依据一种“协定”来动态地扩展它。那么使用设计模式还有哪些好处? 2.1 设计模式 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的。设计模式使代码编制真正工程化,设计模式是软件工程的基石。 GOF(设计模式作者简称)设计模式这本书第一次将设计模式提升到理论高度,并将之规范化,该书提出了
2、 23 种基本设计模式。自此,在可复用面向对象软件的发展过程中,新的大量的设计模式不断出现。 很多人都知道 Java 是完全面向对象的设计和编程语言,但是由于接受教育以及经验的原因,大多数程序员或设计人员都是从传统的过程语言转变而来,因此在思维习惯上要完全转变为面向对象的设计和开发方式是困难的,而学习设计模式可以更好地帮助和坚固这种转变。 凡是学习完成设计模式的人都有一种类似重生的感觉,这种重生可以从很多方面去解释。换一种新的角度来看待和解决问题应该是一种比较贴切的解释,而这种新的思维角度培养属于基础培训,因此,设计模式是学习 Java 的必读基础课程之一。 由于设计模式概念比较抽象,对于初学
3、者学习有一定的难度,因此结合 Jive 论坛系统学习设计模式将是一种很好的选择。 掌握了设 计模式,将会帮助程序员或设计人员以更加可重用性、可伸缩性的眼光来开发应用系统,甚至开发通用的框架系统。框架系统是构成一类特定软件可复用设计的一组相互协作的类,主要是对应用系统中反复重用部分的提炼,类似一种模板,这是一种结构性的模板。 框架通常定义了应用体系的整体结构、类和对象的关系等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节。框架强调设计复用,而设计模式最小的可重用单位,因此框架不可避免地会反复使用到设计模式。关于通用框架系统的设计开发将在以后章节中讨论。 其实 Jive 论坛本身也形
4、成了一个 基于 Web 结构的通用框架系统,因为它很多设计思想是可以重用的,例如设定一个总体入口,通过入口检查用户的访问控制权2 限,当然还有其他各方面的功能实现方式都是值得在其他系统中借鉴的,也正因为它以模式的形式表现出来,这种可重用性和可借鉴性就更强。 2.2 ForumFactory 与工厂模式 工厂模式是 GOF 设计模式的主要常用模式,它主要是为创建对象提供了一种接口,工厂模式主要是封装了创建对象的细节过程,从而使得外界调用一个对象时,根本无需关心这个对象是如何产生的。 在 GOF 设计模式中,工厂模式分为工厂方法模式和抽象工厂模式。两者主要区别是,工厂方法是创建一种产品接口下的产品
5、对象,而抽象工厂模式是创建多种产品接口下的产品对象,非常类似 Builder 生成器模式。在平时实践中,使用较多的基本是工厂方法模式。 以类 SampleOne 为例,要创建 SampleOne 的对象实例 : SampleOne sampleOne = new SampleOne(); 如果 Sample 类有几个相近的类: SampleTwo 或 SampleThree,那么创建它们的实例分别是: SampleTwo sampleTwo = new SampleTwo(); SampleThree sampleThree = new SampleThree(); 其实这 3个类都有一些共同
6、的特征,如网上商店中销售书籍、玩具或者化妆品。虽然它们是不同的具体产品,但是它们有一个共同特征,可以抽象为“商品”。日常生活中很多东西都可以这样高度抽象成一种接口形式。上面这 3 个类如果可以抽象为一个统一接口 SampleIF,那么上面语句就可以成为: SampleIF sampleOne = new SampleOne(); SampleIF sampleTwo = new SampleTwo(); SampleIF sampleThree = new SampleThree(); 在实际情况中,有时并不需要同时生成 3 种对象,而是根据情况在 3 者之中选一个。在这种情况下,需要使用工厂
7、方法来完成了,创建一个叫 SampleFactory的抽象类: public class SampleFactory public abstract SampleIF creator(); 3 在这个抽象工厂类中有一个抽象方法 creator,但是没有具体实现, 而是延迟到它的子类中实现,创建子类 SampleFactoryImp: public class SampleFactoryImp extends SampleFactory public SampleIF creator() /根据其他因素综合判断返回具体产品 /假设应该返回 SampleOne 对象 return new Samp
8、leOne(); 在 SampleFactoryImp 中根据具体情况来选择返回 SampleOne、 SampleTwo 或SampleThree。所谓具体情况有很多种:上下文其他过程计算结果;直接根据配置文件中配置。 上述工厂方法模式中涉及到一个抽象产品接口 Sample,如果还有其他完全不同的产品接口,如 Product 等,一个子类 SampleFactoryImp 只能实现一套系列产品方案的生产,如果还需要另外一套系统产品方案,就可能需要另外一个子类SampleFactoryImpTwo 来实现。这样,多个产品系列、多个工厂方法就形成了抽象工厂模式。 前面已经讨论在 Jive中设置了
9、论坛统一入口,这个统一入口就是 ForumFactory,以下是 ForumFactory 的主要代码: public abstract class ForumFactory private static Object initLock = new Object(); private static String className = “ com.Yasna.forum.database.DbForumFactory“; private static ForumFactory factory = null; public static ForumFactory getInstance(Auth
10、orization authorization) if (authorization = null) 4 return null; /以下使用了 Singleton 单态模式,将在 2.3 节讨论 if (factory = null) synchronized(initLock) if (factory = null) . /从配置文件中获得当前 className try /动态装载类 Class c = Class.forName(className); factory = (ForumFactory)c.newInstance(); catch (Exception e) return
11、 null; /返回 proxy.用来限制授权对 forum 的访问 return new ForumFactoryProxy(authorization, factory,factory.getPermissions(authorization); /创键产品接口 Forum 的具体对象实例 public abstract Forum createForum(String name, String description) 5 throws UnauthorizedException, ForumAlreadyExistsException; /创键产品接口 ForumThread 的具体对
12、象实例 public abstract ForumThread createThread(ForumMessage rootMessage) throws UnauthorizedException; /创键产品接口 ForumMessage 的具体对象实例 public abstract ForumMessage createMessage(); . ForumFactory 中提供了很多抽象方法如 createForum、 createThread 和createMessage()等,它们是创建各自产品接口下的具体对象,这 3 个接口就是前面分析的基本业务对象 Forum、 ForumTh
13、read 和 ForumMessage,这些创建方法在 ForumFactory 中却不立即执行,而是推迟到 ForumFactory 子类中实现。 ForumFactory 的子类实现是 com.Yasna.forum.database.DbForumFactory, 这是一种数据库实现方式。即在 DbForumFactory 中分别实现了在数据库中createForum、 createThread 和 createMessage()等 3种方法,当然也提供了动态扩展到另外一套系列产品的生产方案的可能。如果使用 XML 来实现,那么可以编制一个 XmlForumFactory 的具体工厂子类
14、来分别实现 3 种创建方法。 因此, Jive 论坛在统一入口处使用了抽象工厂模式来动态地创建论坛中所需要的各种产品,如图 3-4 所示。 6 图 3-4 ForumFactory 抽象工厂模式图 图 3-4中, XmlForumFactory 和 DbForumFactory 作为抽象工厂 ForumFactory 的两个具体实现,而 Forum、 ForumThread 和 ForumMessage 分别作为 3 个系列抽象产品接口,依靠不同的工厂实现方式,会产生不同的产品对象。 从抽象工厂模式去理解 Jive 论坛统一入口处,可以一步到位掌握了几个类之间的大概关系。因为使用了抽象工厂模式
15、这种通用的设计模式,可以方便源码阅读者快速地掌握整个系统的结构和来龙去脉,图 3-4这张图已经初步展示了 Jive的主要框架结构。 细心的读者也许会发现,在上 面 ForumFactory 有一个 getInstance 比较令人费解,这将在 2.3 节进行讨论。 7 2.3 统一入口与单态模式 在上面 ForumFactory 的 getInstance 方法使用单态( SingleTon)模式。单态模式是保证一个类有且仅有一个对象实例,并提供一个访问它的全局访问点。 前面曾提到 ForumFactory 是 Jive 提供客户端访问数据库系统的统一入口。为了保证所有的客户端请求都要经过这个
16、 ForumFactory,如果不使用单态模式,客户端下列调用语句表示生成了 ForumFactory 实例: ForumFactory factory = new DbForumFactory(); 客户端每发生一次请求都调用这条语句,这就会发生每次都生成不同 factory对象实例,这显然不符合设计要求,因此必须使用单态模式。 一般在 Java 实现单态模式有几种选择,最常用而且安全的用法如下: public class Singleton private Singleton() /在自己内部定义自己一个实例,是不是很奇怪 /注意这是 private,只供内部调用 private stat
17、ic Singleton instance = new Singleton(); /这里提供了一个供外部访问本 class 的静态方法,可以直接访问 public static Singleton getInstance() return instance; 单态模式一共使用了两条语句实现:第一条直接生成自己的对象,第二条提供一个方法供外部调用这个对象,同时最好将构造函数设置为 private,以防止其他程序员直接使用 new Singleton 生成 实例。 还有一种 Java 单态模式实现: public class Singleton private Singleton() 8 priv
18、ate static Singleton instance = null; public static synchronized Singleton getInstance() if (instance=null) instance new Singleton() return instance; 在上面代码中,使用了判断语句。如果 instance 为空,再进行实例化,这成为lazy initialization。注意 getInstance()方法的 synchronized,这个synchronized 很重要。如果没有 synchronized,那么使用 getInstance()在第
19、一次被访问时有可能得到多个 Singleton 实例。 关于 lazy initialization 的 Singleton 有很多涉及 double-checked locking (DCL)的讨论,有兴趣者可以进一步研究。一般认为第一种 形式要更加安全些;但是后者可以用在类初始化时需要参数输入的情况下。 在 Jive 的 ForumFactory 中采取了后者 lazy initialization 形式,这是为了能够动态配置指定 ForumFactory 的具体子类。在 getInstance 中,从配置文件中获得当前工厂的具体实现,如果需要启动 XmlForumFactory,就不必修
20、改ForumFactory 代码,直接在配置文件中指定 className 的名字为XmlForumFactory。这样通过下列动态装载机制生成 ForumFactory 具体对象: Class c = Class.forName(className); factory = (ForumFactory)c.newInstance(); 这是利用 Java 的反射机制,可以通过动态指定 className 的数值而达到生成对象的方式。 使用单态模式的目标是为了控制对象的创建,单态模式经常使用在控制资源的访问上。例如数据库连接或 Socket 连接等。单态模式可以控制在某个时刻只有一个线程访问资源
21、。由于 Java 中没有全局变量的概念,因此使用单态模式有时可以起到这种作用,当然需要注意是在一个 JVM 中。 2.4 访问控制与代理模式 仔细研究会发现,在 ForumFactory 的 getInstance 方法中最后的返回值有些奇怪。按照单态模式的概念应该直接返回 factory 这个对象实例,但是却返回了9 ForumFactoryProxy 的一个实例,这实际上改变了单态模式的初衷。这样客户端每次通过调用 ForumFactory的 getInstance返回的就不是 ForumFactory的惟一实例,而是新的对象。之所以这样做是为了访问权限的控制,姑且不论这样做的优劣,先看看
22、什么是代理模式。 代理模式是属于设计模式结构型模 式中一种,它是实际访问对象的代理对象,或者影子对象,主要达到控制实际对象的访问。这种控制的目的很多,例如提高性能等。即远程代理模式,这种模式将在以后章节讨论。 其中一个主要的控制目的是控制客户端对实际对象的访问权限。在 Jive 系统中,因为有角色权限的分别,对于 Forum、 ForumThread 和 FroumMessage 的访问操作必须经过权限机制验证后才能进行。 以 ForumFactoryProxy 中的 createForum 方法为例,其实 ForumFactoryProxy也是 FroumFactory 的一种工厂实现,它的
23、 createForum 具体实现如下: public Forum createForum(String name, String description) throws UnauthorizedException, ForumAlreadyExistsException if (permissions.get(ForumPermissions.SYSTEM_ADMIN) Forum newForum = factory.createForum(name, description); return new ForumProxy(newForum, authorization, permissi
24、ons); else throw new UnauthorizedException(); 在这个方法中进行了权限验证,判断是否属于系统管理员。如果是,将直接从DbForumFactory对象 factory的方法 createForum中获得一个新的 Forum对象,然后再返回 Forum 的子类代理对象 ForumProxy。因为在 Forum 中也还有很多属性和操作方法,这些也需要进行权限验证。 ForumProxy 和 ForumFactoryProxy起到类似的作用。 10 Jive 中有下列几个代理类: ForumFactoryProxy:客户端和 DbForumFactory 之
25、间的代理。客户端访问DbForumFactory的任何方法都要先经过 ForumFactoryProxy相应方法代理一次。以下意思相同。 ForumProxy:客户端和 DbForum 之间的代理,研究 Forum 对象的每个方法,必须先看 ForumProxy 对象的方法。 ForumMessageProxy:客户端和 DbForumMessage 之间的代理。 ForumThreadProxy:客户端和 DbForumThread 之间的代理。 User 和 Group 也有相应的代理类。 由以上分析看出,每个数据对象都有一个代理。如果系统中数据对象非常多,依据这种一对一的代理关系,会有很
26、多代理类,将 使系统变得不是非常干净,因此可以使用动态代理来代替这所有的代理类,具体实现将在以后章节讨论。 2.5 批量分页查询与迭代模式 迭代( Iterator)模式是提供一种顺序访问某个集合各个元素的方法,确保不暴露该集合的内部表现。迭代模式应用于对大量数据的访问, Java Collection API中 Iterator 就是迭代模式的一种实现。 在前面章节已经讨论过,用户查询大量数据,从数据库不应该直接返回ResultSet,应该是 Collection。但是有一个问题,如果这个数据很大,需要分页面显示。如果一下子将所有页面要显示的数据都查询出来放在 Collection,会影响性能。而使用迭代模式则不必将全部集合都展现出来,只有遍历到某个元素时才会查询数据库获得这个元素的数据。 以论坛中显示帖子主题为例,在一个页面中不可能显示所有主题,只有分页面显示,如图 3-5所示。 图 3-5中一共分 15 页来显示所有论坛帖子,可以从显示 Forum.jsp 中发现下列语句可以完成上述结果: ResultFilter filter = new ResultFilter(); /设置结果过滤器 filter.setStartIndex(start); /设置开始点 filter.setNumResults(range); /设置范围
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。