资源描述
毕业论文--论坛系统中设计模式的应用
目录
1 引言 2
2 设计模式概述 3
3系统分析 4
3.1系统用例图 4
3.2系统主要功能模块 4
3.2.1信息浏览模块 4
3.2.2信息发布模块 4
3.2.3论坛搜索模块 5
3.2.4论坛管理模块 5
3.2.5用户管理模块 5
3.2.6用户组管理模块 5
3.2.7系统管理模块 6
4系统设计 7
4.1系统主要业务对象设计 7
4.2系统主要模块设计 8
4.2.1系统整体框架设计 8
4.2.2权限设置模块设计 10
4.2.3缓冲机制模块设计 11
4.2.4 批量分页显示模块设计 12
5系统实现 14
5.1系统结构实现 14
5.2 系统主要模块实现 14
5.2.1 系统整体框架实现 14
5.2.2权限设置模块实现 17
5.2.3缓冲机制模块实现 24
5.2.4批量分页显示模块实现 24
结论 26
致谢 27
参考文献 28
1 引言
从挪威奥斯陆大学和挪威计算中心共同研制的Simula 67语言诞生到随后的Smalltalk-76和80语言,再到如今的C++和Java语言,面向对象的方法得到了迅速的发展。面向对象分析(Object-Oriented Analyst,OOA),面向对象设计(Object-Oriented Design,OOD),面向对象编程(Obejct-Orinted Programme,OOP)已经成为了软件开发的主流。
然而,运用面向对象设计系统是比较不易的,特别是要设计可复用可维护的面向对象软件就更加困难。你必须要找到相关的对象,以适当的粒度将它们归类,并建立对象之间的关系。这种设计不仅要针对目前的问题,还要对将来的问题和需求也要有足够的通用性,同时也希望避免重复设计。
设计模式可以帮助我们针对所遇到的很多问题给出结构合理、易于复用、易于维护的示范,使我们更快更好地完成系统设计
论坛系统是我们网络交流使用最为繁频的系统之一,其功能较为简单,但应用却比较广泛,目前在网络上到处可见,简单构建这样一个系统是比较容易的,但要想构建一个性能较好,扩展性较强的论坛系统却是不易。
国内较出名的“动网论坛”,用微软的ASP编写的,由于VBSRCIPT脚本语言自身的限制,很难将业务逻辑层与界面层很好的分离,造成代码的混乱,这给系统后期的维护,扩展增加了很大的成本。我在大部分ASP系统中所看到的都是这种情况。选择JAVA语言来开发可以很好运用面向对象的特性(继承、多态、封装)达到所需的要求,然而如何组织类与类之间的关系,使系统具有灵活性,复用性的同时,不致使设计混乱,这是我一直思考的问题。因此利用前人总结的设计模式设计开发论坛系统具有一定的通用性。
本系统主要采用JAVA语言编写,具有跨平台,组件复用等特点,系统对论坛的权限,性能,内容显示及风格等主要功能上采用了权限过滤,缓冲机制,批量分页显示和自定义风格等技术手段,在设计上应用了单件、工厂、代理、迭代等设计模式,各层间的耦合度较为松散,总体上本系统具有较好的性能,较好的扩展性及通用性。
2 设计模式概述
模式研究最早起源于建筑工程设计大师Chrisopher Alexander的关于城市规划和建筑设计的著作。他说:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”[AIS+77,第10页]。尽管Alexander所指的是城市和建筑模式,但他的思想也同样适用于面向对象设计领域。
设计模式在软件设计行业中的起源可以追溯到1987年,由Ward Cunningham和Kent Beck共同编写的一篇”Using Pattern Languages for Object-Oriented Programs(使用模式语言做面向对象的程序)”的论文(发表于OOPSLA’87 IN Orlando)。然而,在面向对象的领域使用模式化方法研究的开创性著作是《Design Patterns》(发表于1995年)。书中作者为四位面向对象领域专家:Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides通常被戏称为“四人帮”(Gang of Four,或GoF)。
不同的人不同的出发点对设计模式的理解是不同的。《Design Patterns》一书中这样阐述设计模式:设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。一个设计模式命名、抽象和确定了一个通用设计的主要方面这些设计结构能被用来构造可复用的面向对象设计。每一个设计模式都集中于一个特定的面向对象设计问题或设计要点,描述了什么时候使用它,在另一些设计约束条件下是否还能使用,以及使用的效果和如何取舍。
目前,设计模式已被广泛地应用于软件行业,它把面向对象的理念发挥到了极至,对许多问题,提出了实际的解决方案。
以下,本文就论坛系统实现中设计模式的应用进行阐述,主要以论坛系统分析、设计、实现为流程进行。
3系统分析
论坛系统是网络交流的一种主要互动功能系统。通过论坛系统,用户可以共同就某个话题不断进行讨论,通过发贴功能发布新的话题,通过回贴功能回复别人的话题。论坛系统还可以允许管理员动态地创建新的论坛、管理论坛、管理用户等。
本系统用例图及主要功能模块如下:
3.1系统用例图
管理员
登录
用户组管理
用户管理
论坛管理
系统管理
普通用户
用户注册
信息发布用户注册
信息浏览
登录
论坛搜索
图3.1 系统用例图
3.2系统主要功能模块
3.2.1信息浏览模块
功能说明:提供本论坛、主题、帖子信息等的浏览,提供分页显示
前置条件:有信息浏览权限,通常未注册用户也可浏览,由后台权限设置
论坛浏览信息包括论坛名称,描述,论坛主题数,总帖子数,最后更新时间,发帖用户等
主题浏览信息包括主题名,作者,回复数,最后回复时间及回复作者名等
帖子浏览信息包括帖子名称,内容,发帖时间,作者,作者发帖子数,注册时间等
3.2.2信息发布模块
功能说明:提供主题、帖子信息的发布
前置条件:有信息发布权限(由后台权限设置)
主题发布内容包括主题名,内容等信息
帖子回复主要包括帖子标题,帖子内容等
3.2.3论坛搜索模块
功能说明:提供论坛信息的搜索功能,方便用户检索论坛中的相关讨论话题
3.2.4论坛管理模块
功能说明:提供创建、删除、管理论坛功能
前置条件:有管理员权限
创建论坛信息包括:论坛名称,描述,论坛的默认权限
管理论坛包括:
编辑论坛属性:标题、描述
设置论坛权限:为所有将使用的论坛设置全局权限策略。 权限总是附加的,论坛的最终权限将是全局权限加上论坛特定的权限,权限包括浏览信息、创建主题、回复帖子,及调整
筛选论坛信息:筛选功能允许在论坛的主题和消息可见前进行筛选
编辑论坛信息:删除论坛中的某一主题或帖子
3.2.5用户管理模块
功能说明:提供添加用户、编辑用户、删除用户,浏览用户功能
前置条件:有管理员权限
添加用户信息包括:用户名,呢称,E-mail
编辑用户信息包括:用户名,呢称,E-mail,姓名是否公开,E-mail是否公开,口令
浏览用户包括:浏览所有用户,每个用户信息包括用户名,呢称,E-mail,姓名是否公开,E-mail是否公开;还包括概括ID查询用户
3.2.6用户组管理模块
功能说明:提供添加用户组、编辑用户组、删除用户组功能
前置条件:有管理员权限
添加用户组信息包括:用户组名、描述
编辑用户组信息包括:编辑用户组基本信息(用户组名、描述),添加和删除用户
3.2.7系统管理模块
功能说明:提供添加全局权限设置、搜索设置、缓权设置、数据库设置、数据库导入导出、外观设置、基本统计、监控设置功能
前置条件:有管理员权限
全局权限设置描述:为所有将使用的论坛设置全局权限策略。 权限总是附加的,论坛的最终权限将是全局权限加上论坛特定的权限。权限包括浏览信息、创建主题、回复帖子及调整帖子
搜索设置描述:搜索引擎将定期的将新消息加入可搜索消息数据库。设置信息包括:设置搜索状态(激活或者关闭), 索引化设置(手动还是自动),更新索引,重建索引
缓权设置描述:论坛依赖于它的缓存有效的处理论坛数据以编辑缓存的大小调整成最小的内存使用或者最好的性能,包括设置缓存(大、中、小、自定义),浏览系统缓存情况(包括各对象缓存大小)
数据导入和导出描述:允许你向Jive论坛中写入数据或者从中读取数据。所有的数据都使用Jive XML 格式
数据库信息浏览包括:数据库属性、JDBC驱动属性、数据库功能
外观设置描述:编辑Jive论坛的缺省外观,包括字体设置、颜色设置、描述、页面头、主题模式等
监控设置描述:监控允许用户跟踪他们感兴趣的主题,在有更新的情况下发送电子邮件提醒他包括Email监控设置
4系统设计
4.1系统主要业务对象设计
本系统业务对象主要分为Forum(论坛)、ForumThread(论坛主题)和ForumMessage(论坛帖子),User(用户),UserGroup(用户组), ForumPermissions(论坛权限)等。
系统包括0个或多个论坛,一个论坛包括0个或多个论坛主题,一个论坛主题包括0个或多个回帖,其关系类似于如下的树型结构图4.1,类关系图如4.2。
--Froum
--FroumThread
--ForumnThread
---ForumMessage
---ForumMessage
---ForumnThread
…
图4.1 Forumn、ForumThread、ForumMessage树型结构图
Forum
ForumThread
ForumThread
ForumMessage
ForumMessage
图4.2 系统业务对象关系图
系统用户有三类,一为匿名用户,二为注册用户,三为管理员。一个用户组有0个或多个用户,可以通过对用户组进行授权,进行对系统进行权限访问。
4.2系统主要模块设计
本系统的设计应用了多种设计模式,主要有单例模式,工厂模式,代理模式,迭代模式,观察者模式,过滤模式等,其主要模式设计与系统总体关系如图4.3所示,在以下的论述过程中主要从模式说明和模式应用两个部分进行阐述。
单例模式
工厂模式
代理模式
缓冲
迭代模式
图4.3 系统设计模式框图
4.2.1系统整体框架设计
系统整体框架设计说明:在系统整体设计上为了系统具有更好的扩展性以及实现对论坛各对象(如论坛、主题、帖子、用户、权限等)的统一管理,在系统整体框架设计上主要应用了创建型设计模式中的单例模式和工厂模式。
创建型模式 (Creational Patterns):创建型模式抽象了实例化过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。它可以将系统的具体的实现类的信息封装起来,隐藏这些类的实例相互关系的细节。这会使系统的设计更加的灵活,单件模式和工厂模式便是其中的两种。
1)统一入口与单件(SingleTon)模式
模式说明:单件模式是保证一个类有且仅有一个对象实例,并提供一个访问它的全局访问点。比如一个系统中虽然可以有许多打印机,但却只应该有一个打印假脱机(printer spooler),一个窗口管理器。一个数字滤波器只能有一个A/D转换器等。我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量可以使得一个对象被访问,但它不能防止你实例化多个对象,一个较好的办法是让自身保存它的唯一实例 ,这个类可以保证没有其他实例可被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。
模式应用:系统为了实现对论坛各对象(如论坛、主题、帖子、用户、权限等)的管理,通过设定一个统一的入口(ForumFactory),所有客户端访问都必须从这个入口进入,系统的一些功能都在这个入口产生,如创建、删除、得到坛论,发布主题,帖子,增加用户等都在这个入口统一产生,必须保证这个入口的唯一性,应用单件模式可以完成这个设计,如图4.4所示
jsp
jsp
ForumFactory
图4.4 入口示意图
2) FroumnFactory与工厂(Factory)模式
模式说明:工厂模式包括两类:
抽象工厂(Abstract Factory)模式:提供一个创建一系列相关或相互对象的接口,而无需指定它们具体的类;考虑一个用户界面支持多种视觉效果,不同的视觉效果有不同的窗口、按钮等外观和行为,如何保证不同视觉效果风格间是可移植性的,并且可以扩展呢,很明显,我们不能为一个特定的视觉外观进行硬编码它的窗口组件。解决这类问题,我们可以定义一个抽象的WidgetFactory类,这个类声明一个用来创建每一个类基本窗口组件的接口。每一类窗口组件都有一个抽象类,而具体子类则实现了窗口组件的视觉风格。对于每一个抽象窗口组件类,WidgetFactory接口都有一个返回新窗口组件对象的操作。客户调用这些操作以获得窗口组件实例,但并不知道他们正在使用的是哪些具体类。
工厂方法(Factory Method)模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。它使一个类的实例化延迟到其子类。工厂方法不再将与特定应用有关的类绑定到你的代码中。
模式应用:一个论坛系统可能有多种实现方式,比如数据库实现和XML方式实现,如何能设计在不同的实现时,方便地进行移植呢?在系统便使用工厂模式来进行设计,以使系统具有良好的移植性,主要是对不同的论坛对象设计了相应的接口如Forumn(论坛接口), ForumThread(论坛主题接口), ForumMessage(论坛帖子接口),User(用户接口), Group(用户组接口)。在ForumFactory抽象类中,利用接口进行相应的设计而不管具体是哪种实现(可能是数据库实现或XML方式实现),如创建论坛(public abstract Forum createForum(String name, String description)),创建主题(abstract ForumThread createThread(ForumMessage rootMessage)),创建帖子(public abstract ForumMessage createMessage())等皆是面向接口方法的,而具体的实现却延迟到了特定的数据库实现DBForumFactory当中,各接口与实现关系如下:
ForumThread
ForumMessage
Forum
ForumFactory
XMLForumFactory
DBForumFactory
DBForum
XMLForum
DBForumThread
XMLForumThread
DBForumMessage
XMLForumMessage
图4.5 ForumFactory与抽象工厂模式图
4.2.2权限设置模块设计
权限设置模块设计说明:权限设置是各种系统功能的一部分,如何进行权限地设计是很重要的,在复杂的系统中通常通过用户、角色、权限三人对象进行设计,在本系统主要应用了结构型设计模式中的代理模式进行设计。
结构型模式(Structural Patterns):结构型模式涉及到如何组合类和对象以获得更在的结构。结构型模式采用继承方式来组合接口或实现。一个最简单的例子是采用多重继承方法将两个以上的类组合成一个类,结果这个类包含了所有父类的性质 。结构型模式描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,因此它具有较大的灵活性。代理模式便是其中的一种。
访问控制与代理(Proxy)模式:
模式说明:为其他对象提供一种代理以控制对这个对象的访问。考虑一个可以在文档中嵌入图形的文档编辑器,有些图形对象(如光栅图像)的创建开销很大,我们在打开文档的时候有时并不需要同时创建它,只有在需要时才创建。我们如何才能隐藏根据需要创建图像这一事实,而不使实现变得复杂,影响绘制和格式化呢?解决方案是使用一个图像代理对象,替代真正的图像,只有文档激活图像操作以显示这个图像时,代理才真正创建图像。
模式应用:在论坛系统中,有四种权限,不同的权限对系统的访问是不同的,因此对于各大对象如Forum、ForumThread和FroumMessage等的访问操作必须经过权限机制验证后才能进行(如图4.6)。本系统为每个业务对象添加一个代理类,在访问每个对象前先访问代理类,从而达到权限控制的目的。Proxy 模式一直贯穿系统的始终, 几乎所涉及到的对象都需要,其通用结构如图4.7
访问控制代理
缓存对象
Froum等对象
客户端
图4.6 系统主要对象的访问
Interface A
Proxy A
Database A
图4.7 系统Proxy 模式设计通用结构图
本系统中设计有下列几个代理类:
ForumFactoryProxy:客户端和DbForumFactory之间的代理。客户端访问DbForumFactory的任何方法都要先经过ForumFactoryProxy相应方法代理一次。以下意思相同。
ForumProxy:客户端和DbForum之间的代理,研究Forum对象的每个方法,必须先看ForumProxy对象的方法。
ForumMessageProxy:客户端和DbForumMessage之间的代理。
ForumThreadProxy:客户端和DbForumThread之间的代理。
User和Group也有相应的代理类。(略)
4.2.3缓冲机制模块设计
缓冲机制模块设计说明:论坛系统的性能是评价系统的一个重要指标,io操作的速度远远无法满足用户对论坛信息浏览的速度要求,一个很好的解决方案就是使用缓存机制,在本系统中,为了避免把缓存操作和具体数据存取操作合在一起,从而造成代码的庞大,在这个功能模式的设计上主要应用了结构型设计模式中的代理模式
缓存机制与代理(Proxy)模式
模式说明:同上。
模式设计:本系统虽然未显式地应用代理模式特征来设计缓存机制,但本系统所采用的缓存机制实质上也是一种代理模式。如图4.6所示:
缓存机制从原理上讲比较简单,就是在原始数据第一次读取后保存在内存中,下次读取时,就直接从内存中读取。原始数据有可能保存在持久化介质或网络上
本系统的缓存机制设计为三层:第一层提供HashMap、LinkedListedlist等数据结构以实现缓存机制,第二层调用底层数据结构以提供论坛对象的缓存,第三层向Jsp页面提供访问接口。
第一层底层数据结构层的设计是把所要缓存的对象加到HashMap哈希映射表中,用两个Linkedlist双向链表分别维持着缓存对象,第一个Linkedlist根据缓存对象被访问的先后顺序维持缓存对象,第二个缓存对象根据缓存对象加入的时间维持来缓存对象。如果一个缓存对象被访问到,那么就把它放到链表的最前面,然后不定时地把要缓存的对象加入链表中,把过期对象删除,如此反复。
第二层:中间层是联系上层访问接口和低层数据结构的纽带。它的设计主要是根据ID(对应于数据库中的编号)到缓存中找相应的对象。如果缓存中有该对象就直接得到,没有则去读数据库生成一个新的对象,再把该对象放入缓存中,以便下次访问时能直接得到。
第三层:上层访问接口的设计主要是面向表示层的。
4.2.4 批量分页显示模块设计
批量分页显示模块设计说明:为了提高系统的性能,在本系统中不仅使用了缓存机制,而且在表示层的数据的设计上也应用行为型设计模式中的迭代模式。
行为型模式(Behavioral Patterns):行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻划了在运行时难以跟综的复杂的控制流。它们将你的注意力从控制流转移到对象的联系方式上来。迭代模式是其中的一种。
批量分页查询与迭代(Iterator)模式
模式说明:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。这一模式的关键思想是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器对象中。迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟综当前的元素,也就知道了哪些元素已经遍历过了。
模式设计:迭代模式应用于对大量数据的访问,Java Collection API中Iterator就是迭代模式的一种实现。在一个论坛中当用户查询大量数据,从数据库不应该直接返回ResultSet,应该是Collection。但是有一个问题,如果这个数据很大,需要分页面显示。如果一下子将所有页面要显示的数据都查询出来放在Collection,会影响性能。而使用迭代模式则不必将全部集合都展现出来,只有遍历到某个元素时才会查询数据库获得这个元素的数据。在本系统的设计中,如果论坛的数据量比较大时,首先会根据页面请求,得到相应范围内对象的ID,根据ID先查找所需对象是不否在缓存当中,如果不在然后再进行数据数据库查询,查询结果所返回的结果应该是一个迭代器。这样的设计可以提高不少的性能。
5系统实现
5.1系统结构实现
本统为一WEB应用系统,前端为浏览器,后端为数据库服务器,WEB容器采用TOMCAT,操作平台需安装jdk, 整体使用JSP+JAVABEAN技术。(结构如图5.1)
jdbc
http
客户端
JSP
JAVABEAN
数据库服务器
Tomcat
图5.1 系统结构图
5.2 系统主要模块实现
5.2.1 系统整体框架实现
1) 统一入口实现
ForumFactory是系统提供客户端访问数据库系统的统一入口。为了保证所有的客户端请求都要经过这个ForumFactory,如果不使用单态模式,客户端下列调用语句表示生成了ForumFactory实例:
ForumFactory factory = new DbForumFactory();
客户端每发生一次请求都调用这条语句,这就会发生每次都生成不同factory对象实例,这显然不符合设计要求,因此必须使用单态模式
public class ForumFactory {
private static ForumFactory factory = null;
public static synchronized ForumFactory getInstance() {
if (factory==null)
Class c = Class.forName(className);
factory = (ForumFactory)c.newInstance();
return factory;
}
}
在上面代码中,使用了判断语句。如果factory为空,再进行实例化,这成为lazy initialization。getInstance()方法的synchronized,这个synchronized很重要。如果没有synchronized,那么使用getInstance()在第一次被访问时有可能得到多个factory实例。
2) FroumnFactory实现
面对接口编程,而不是面对对象编程,这是设计的一个基本原则。工厂模式中使用了大量的接口进行实现,如Forumn(论坛接口), ForumThread(论坛主题接口), ForumMessage(论坛帖子接口),User(用户接口), Group(用户组接口),其中最重要的是ForumFactory接口以及其实现类DBForumFactory,ForumFactory接口作为整个系统的入口定义了整个系统的一些重要功能,关键代码如下:
public class ForumFactory {
……
public abstract Forum createForum(String name, String description)//创建论坛
public abstract ForumThread createThread(ForumMessage rootMessage)//创建主题
public abstract ForumMessage createMessage(User user) //创建帖子
public abstract Forum getForum(long forumID) //通过论坛ID得到论坛
public abstract int getForumCount();//得到论坛数
public abstract Iterator forums();//得到论坛迭代器
……
}
DBForumFactory则是ForumnFactory实现数据库存储的相应类,系统的真正实现类,其关键代码如下:
public class DbForumFactory extends ForumFactory {
public Forum createForum(String name, String description) {
Forum newForum = new DbForum(name, description, this);//创建DBForum论坛
}
return newForum;
}
//建立一个主题,参数为根消息
public ForumThread createThread(ForumMessage rootMessage) {
return new DbForumThread(rootMessage, this);
} }
5.2.2权限设置模块实现
以下以创建一个论坛为例,演示应用权限控制的实现,以上部分已经说明了ForumFactory是整个系统的入口,在ForumFactory类的getInstance()方法中,传入一个验证标记(即用户是否有通过验证或拥有相应权限), 最后返回一个 ForumFactoryProxy 的实例(ForumFactoryProxy也是FroumFactory的一种代理实现),关键代码如下:
public abstract class ForumFactory {
……
public static ForumFactory getInstance(Authorization authorization) {
if (authorization == null) {//是否通过验证
return null;
} //代理模式,返回工厂代理……
return new ForumFactoryProxy(authorization, factory,
factory.getPermissions(authorization))
}
在ForumFactoryProxy代理类中,创建论坛的代码代码如下:
public Forum createForum(String name, String description){
if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {
Forum newForum = factory.createForum(name, description);
return new ForumProxy(newForum, authorization, permissions);
}else {
hrow new UnauthorizedException(); }}
在这个方法中进行了权限验证,判断是否属于系统管理员。如果是,将直接从DbForumFactory对象factory的方法createForum中获得一个新的Forum对象,然后再返回Forum的子类代理对象ForumProxy。因为在Forum中也还有很多属性和操作方法,这些也需要进行权限验证。ForumProxy和ForumFactoryProxy起到类似的作用,在本系统中,几乎每个数据对象都有一个代理,如果系统中数据对象非常多,依据这种一对一的代理关系,会有很多代理类,将使系统变得不是非常干净,因此可以使用动态代理来代替这所有的代理类
5.2.3缓冲机制模块实现
缓存机制的实现划分为三层,即底层数据结构,中间层和第上层访问接口
第一层:底层数据结构实现如图5.2:
Cachable
LinkedList
Cache
HashMap
CacheObject
LinkedListNode
图5.2 Jive缓存机制的底层数据结构
LinkListNode是一个双向链表的节点类,previous、next分别记录前后节点的指针,object用于记录所需缓存的对象,timestamp用于记录当前节点被创建时的时间戳。当该时间戳超过该节点的生存周期时,它就会被remove()方法删除掉,关键代码如下:
public class LinkedListNode {//双向链表节点
public LinkedListNode previous;//前向节点
public LinkedListNode next; //后向节点
public Object object;
public long timestamp; //对象加入缓存时间
public LinkedListNode(Object object, LinkedListNode next,
LinkedListNode previous){……}
public void remove() {//移除节点
previous.next = next;
next.previous = previous;
} }
LinkedListNode节点主要用来构成LinkedList链表,而由LinkedList类实现getFirst()、getLast()、addFirst()、addLast()、clear()等链表的基本方法。
缓存机制中最关键的一个类是Cache,这个类中保留着一个HasMap存储缓存对象(因为其存取速度较快),两个LinkedList链表一个按时间存储对象加另一个按访问顺序存储对象,同时这个类中都有设置整个缓存的大小,缓存的命中率等属性,其最关键的是两个方法主要是add()和get()方法 :
add()方法主要是向哈希表中添加一个关键字为Key的缓存对象object,其过程如下:首先把原来的对象移除,然后判断对象的大小,如果太大就不加入缓存,如果缓存足够就新建一个缓存对象,并放入哈希表中,并把把缓存元素的Key放到lastAccessed List链表的最前面,把缓存元素的Key放到ageList链表的最前面,并记下当前时间,最后整理一下缓存,把过期对象和不常访问的对象删掉。关键代码如下:
public class Cache implements Cacheable {
......
public synchronized void add(Object key, Cacheable object) {
remove(key); //先把原来的对象remove掉
int objectSize = object.getSize();
if (objectSize > maxSize * .90) { return; }//如果对象太大,则不加入缓存
size += objectSize; //新建一个缓存对象,并放入哈希表中
CacheObject cacheObject = new CacheObject(object, objectSize);
cachedObjectsHash.put(key, cacheObject);
//缓存元素的Key放到lastAccessed List链表的最前面
LinkedListNode lastAccessedNode = lastAccessedList.addFirst(key);
cacheObject.lastAccessedListNode = lastAccessedNode;
//把缓存元素的Key放到ageList链表的最前面,并记下当前时间
LinkedListNode ageNode = ageList.addFirst(key);
ageNode.timestamp = System.currentTimeMillis();
cacheObject.ageListNode = ageNode;
// 在cullCache()中,把过期对象删掉,
如果缓存还是太满,则调用把lastAccessedList中不常访问的对象删掉
cullCache();
}
}
get()方法完成在哈希表中得到一个关键字为Key的缓存对象object,过程如下:首先清理过期对象,到哈希表中寻找是否有关键字为Key的对象,如果没找到则未命中次数加一,找到则命中次数加一,并将该缓存对象从lastAccessedList链表中取下并插入到链表头部。关键代码如下:
public synchronized Cacheable get(Object key) {
deleteExpiredEntries();// 清理过期对象
CacheObject cacheObject = (CacheObject)cachedObjectsHash.get(key);
if (cacheObject == null) {
cacheMisses++;//没找到则未命中次数加一
return null; }
cacheHits++;//找到则命中次数加一
//将该缓存对象从lastAccessedList链表中取下并插入到链表头部
cacheObject.lastAccessedListNode.remove();
lastAccessedList.addFirst(cacheObject.lastAccessedListNode);
return cacheObject.object;
}
第二层:中间层是联系上层访问接口和低层数据结构的纽带。它的主要功能就是根据ID(对应于数据库中的编号)到缓存中找相应的对象。如果缓存中有该对象就直接得到,没有则去读数据库生成
展开阅读全文