关于设计模式, 这篇文章并不详细解释, 只是结合 Jive 来看看设计模式在一个实际项目中的应用及其整体的设计思想. 所以在读这篇文章前, 假设您对设计模式有一个感性的认识, 对其具体应用以及实现方法有些疑问, 并渴望了解其思想,并使用过 Jive. 本文将一同来探讨这个问题. 为什么选择 Jive 而不是选择一个新的例子重新开始呢? 有以下两个原因: 1, 我们很多人对 bbs 这样一个事物比较熟悉,很清楚 bbs 所具有的一些基本功能, 如果自己作为设计者来设计这样一个 web bbs,会怎么想, 再看看别人是怎么实现的, 有对比才能明白自己设计上的缺点, 看到别人的优点才能更快地进步. 2, Jive 并不是非常地复杂, 并且包括了一个完整的实现方案, 从底层到高层, 从后端到前端, 都有很好的文档, 这些都能更好地帮助我们理解它.
这里我们所用的 Jive 的版本采用其开发者作为正式发布的 1.0 版, 其最新版为 1.21, 对其结构作了少量改动, 主要增加了 jsp tag 的支持, 这种技术不属于我们的讨论范围, 以后有机会可以共同学习.
Jive 中所使用的设计模式, 对设计模式的三种类型 -- 创建型, 结构型,行为型 -- 都有涉及, 这样也能比较全面地了解设计模式. 我们先来自己设计一下,运用面向对象的思想, 可以很容易知道, 整个系统主要需要这几个对象:
- Forum -- 一个讨论区, 也就是一个版面.
- Thread -- 一条线索, 也就是有关同一个主题的所有的回文.
- Message -- 一条消息, 也就是一个用户发的一篇贴子.(以后我们就用"贴子"这个叫法)
- User -- 一个用户, 也就是讨论区的使用者.
好了, 我们需要的东西都在了, 它们之间的关系十分复杂, 怎么把它们组织地很符合我们的思路又能容易扩充呢? 我想大家都有自己的想法了, "我能这么这么做","我可以这样这样设计", 我们一起来看看 Jive 是怎么做的. 下面是其整体结构:
|~~~~~~~~~~~~~~~~~~|
| Skin 设计者 |
|__________________|
| |
| | 使用
/ /
|~~~~~~~~~~~~~~~~~|
| 各种对象的接口 |
|_________________|
| |
| | 被实现
/ /
|~~~~~~~~~~~~|
| 权限控制 |
|____________|
| |
| | 控制
/ /
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
| 对数据库进行操作的各种对象 |
|_____________________________|
| |
| | 取连接
/ /
|~~~~~~~~~~~~~~~~|
| 数据库连接池 |
|________________|
(图 1)
|
下面是其类的大概的继承情况:
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
| Interface A |
|___________________________________|
| |
| implements |
| |
|~~~~~~~~~~~~~~~~~| |
| Proxy A | |
|_________________| |
|
|
|~~~~~~~~~~~~~~~~~~|
| Database A |
|__________________|
(图 2)
|
好了看到这里, 如果您对设计模式有了解的话, 从上面所写的伪名字中, 可以看到一些熟悉的东西. 请让我做一些解释. 上面的图表示的是类的继承关系, A 代表上面所提到的四种对象, Interface A 表示名为 A 的一个接口, 相信大家对接口都不陌生, 接口在 java 中有着重要的作用. Proxy A 表示一个名为 ProxyA 的类,实现 A 接口. Database A 表示名为 DbA 的一个类, 实现 A 接口. 但设计模式并没有从中体现出来,设计模式所要表现的是怎么样更好地组织对象之间的逻辑关系,怎么样才能更好地扩充现有的东西而不需要作很大的改动, 而不仅仅是类的继承.
还有一点需要说明的是, 设计模式总的原则是针对接口编程, 而不关心其具体实现, 这样搭起来的是一个架子, 还需要作许多具体的编程才能真正的完成系统.
下面, 我们就分别从设计模式的三种类型来看 Jive 使用了其中的哪些.
创建型模式 (Creational Patterns)
这一类型的设计模式, 所要表现的是对象的创建过程及和用户所使用的对象之间的关系.
- Jive 中在 Forum 之上又加了一层, ForumFactory, 来实现对 Forum 的一些控制, 比如创建新的讨论区, 删除一个讨论区等等. 这个类实际上是整个系统的入口,jsp 中所做的一切都要从得到这个类的一个实例开始. 它的一些子类和它的关系如下:
|~~~~~~~~~~~~~~~~~|
| ForumFactory | abstract
|_________________|
| |
| extends |
| |
|~~~~~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~~~|
| ForumFactoryProxy | | DbForumFactory |
|____________________| |_________________|
(图 3)
|
我们来看一下得到一个 ForumFactory 实例的过程:
FactoryForum factory = ForumFactory.getInstance(aAuthorization);就得到了 ForumFactory 的实例, 这个最终用户(skin 设计人员)所使用的是它的子类 ForumFactoryProxy 的实例, (其中涉及到另一个模式, 后面将会提到), 但实际上真正在做实际工作的是 DbForumFactory 或者是一个指定的类的实例, 相关代码如下:
From ForumFactory.java
private static String className = "com.coolservlets.forum.database.DbForumFaactory";
// 系统缺省的 ForumFactory 的一个具体的子类.
private static ForumFactory factory = null;
ForumFactory.getInstance()
String classNameProp = PropertyManager.getProperty("ForumFactory.className")
// 可以通过配制文件来选择其他的具体的子类.
if (classNameProp != null) {
className = classNameProp;
}
try {
//Load the class and create an instance.
Class c = Class.forName(className);
factory = (ForumFactory)c.newInstance();
}
catch (Exception e) {
System.err.println("Failed to load ForumFactory class "
+ className + ". Jive cannot function normally.");
e.printStackTrace();
return null;
}
|
它使用的是 Abstract Factory (抽象工厂)设计模式. 给用户一个使用一系列相关对象的接口, 而不需要指定其具体的类. 也就是说, skin 设计人员写的 jsp 中不应该出现new DbForumFactory 之类的语句. Jive 中 AuthorizationFactory 也使用了这个设计模式
- Jive 中有一个很不错的想法, 就是对贴子的内容和标题可以进行过滤, 比如过滤 html过滤一些脏话, 对附加的代码进行高亮显示, 转换链接等等. 如果我要实现这样的功能, 有有下几种方法: (1) 在 Message.getBody() getSubject() 中进行控制, (2) 在 Thread 中得得Message 后进行转换. 还需要考虑的问题是这些过滤的操作必须能够很方便地添加删除. 不不的目标所用的设计方法是不一样的, Jive 是这样做的: 以版面为主, 把这些过滤器看作是鞍婷的属性, 过滤器只对其所属的版面有效, 所以 Jive 中使用了 (2), 这并不是主要的, 重要要是这些过滤器该怎么来组织. 我们先来看看需求: 能动态添加删除, 功能类似, 贴子的显示示其具体怎么创建, 如何表现无关. 似乎目标只有一个 -- Prototype(原型) 设计模式. 看看Jive 的具体实现.
|~~~~~~~~~~~~~~~~~~~~|
| ForumMessage |
|____________________|
|
| implements
|
|~~~~~~~~~~~~~~~~| Prototype |~~~~~~~~~~~~~~~~~~~~~|
| ForumThread |-----------> | ForumMessageFilter |
|----------------| |---------------------|
| getMessage() o | | clone() |
|______________|_| |_____________________|
| / |
|~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
| aFilter.clone()| | HighlightCode | | HTML |
|________________| |---------------| |-------------| ......
| clone() o | | clone() o |
|___________|___| |___________|_|
| |
|~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~|
| 返回一个实例 | | 返回一个实例 |
|_______________| |_______________|
(图 4)
|
上图作了少许的简化. Jive 用的时候是把这些过滤器存在数据库中, 可以动态设置 属性, 比较方便. 来看一些代码:
From: DbForumThread.java
public ForumMessage getMessage(int messageID)
throws ForumMessageNotFoundException
{
ForumMessage message = factory.getMessage(messageID);
//Apply filters to message.
message = forum.applyFilters(message);
//通过 Forum 来实现, 因为 Filter 是 Forum 的属性,
//Thread 只能通过 Forum 的接口来访问.
return message;
}
From: DbForum.java
public ForumMessage applyFilters(ForumMessage message) {
for (int i=0; i < filters.length; i++) {
message = filters[i].clone(message);
}
//可能会有多个过滤器, 依次来操作.
return message;
}
|
|
|
结构型模式 (Structural Patterns)
这一类的模式关心类和对象之间怎么组织起来形成大的结构. 主要使用继承来组织接口或实现.
我们再接着思考一下, 用户之间应该有所区别, 有 Guest 用户, 可以让他来看一看, 但不能发贴子, 正式用户可以发贴子, 查看自己的个人信息, 版面管理者(称之为版主)应该可以控制贴子, 比如加上适当的标记, 收入精华区, 甚至删除贴子等等, 而系统管理者应该具有更高的权限, 比如开新的版面, 删除用户等操作. 怎么实现这个功能呢? 我们知道, Jive 中所有实际的操作都是由 database 目录下的类所实现的,如果把权限控制加到数据库这一层的话, 这一层不但臃肿, 而且写好以后, 如果要改的话, 需要修改的地方很多, 还容易出错, 所以可以在这一层之上再加一层, 单独进行权限控制. 这样就把 "该不该做" 和 "怎么做" 分割开来, 利于以后修改. 其实这也是面象对象的一个思想 -- 一个对象不要负担太多的责任. 这种方法在设计模式中称为 Proxy (代理) 模式. 好比生产厂家和代理商的关系. (当然, 在 Jive 中这个比喻不太合适). Proxy 的目的就是给另一个对象提供一个代理来控制对它的访问. Proxy 模式一直贯穿 Jive 的始终, 几乎所涉及到的对象都需要. 其结构如图 2所示. 从前面已经知道, ForumFactory 是整个系统的开始. 再来看看 ForumFactory 的代码:
From ForumFactory.java
ForumFactory.getInstance() 的最后:
ForumFactoryProxy proxy = new ForumFactoryProxy(
factory,
authorization,
factory.getPermissions(authorization)
);
return proxy;
|
前面得到的 factory 是 DbForumFactory 的实例, 这里把这个实例又用ForumFactoryProxy 封装起来. 最后返回一个 ForumFactoryProxy 的实例. 也就是说 jsp skin 的设计者所用的 ForumFactory 实际上是 ForumFactoryProxy. 接着看看 ForumFactoryProxy 里发生了什么事, 那一个小片段做例子: 其构造函数中的 Factory 就是一个 DbForumFactory 的实例, 由它来做具体的工作. Authorization 可以认为是一个认证过的当前用户(指实际的浏览器的使用者),ForumPermissions 可以认为是当前用户的权限.
public Forum createForum(String name, String description)
throws UnauthorizedException
{
//这里就对权限进行了检查, 具有系统管理员权限, 则可以进行相应的操作,
//否则抛出异常.
if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {
Forum newForum = factory.createForum(name, description);
return new ForumProxy(newForum, authorization, permissions);
}
else {
throw new UnauthorizedException();
}
}
public Forum getForum(int ID) throws ForumNotFoundException,
UnauthorizedException
{
Forum forum = factory.getForum(ID);
ForumPermissions forumPermissions = forum.getPermissions(authorization);
//Create a new permissions object with the combination of the
//permissions of this object and tempPermissions.
ForumPermissions newPermissions =
new ForumPermissions(permissions, forumPermissions);
//Check and see if the user has READ permissions. If not, throw an
//an UnauthorizedException.
if (!(
newPermissions.get(ForumPermissions.READ) ||
newPermissions.get(ForumPermissions.FORUM_ADMIN) ||
newPermissions.get(ForumPermissions.SYSTEM_ADMIN)
))
{
throw new UnauthorizedException();
}
// 同上所述.
// 这里得到的 forum, 是一个 DbForum 的实例, 跟 ForumFactory 一样,
// 返回一个封装过的代理对象, 来对 forum 进行权限控制.
return new ForumProxy(forum, authorization, newPermissions);
}
|
其他所有的对象都是类似的. 这里就不再赘述.
行为型模式 (Behavioral Patterns)
这一类的模式关心的是算法以及对象之间的任务分配. 它所描述的不仅仅是对象或类的设计模式, 还有它们之间的通讯模式.
1, 下来看看怎么从一个 Forum 中得到一些 Thread. 当然这里要涉及到数据库, 我们先设计一个最简单的数据库表, 表名: thread, 字段 ThreadID int, ForumID int, 其他内容我们不关心. 然后比如 Forum 中的一个方法, getThreads() 来返回当前 Forum 所有的 Thread. 然后就可以这样做:
public ForumThread[] getThreads()
{
1, 从数据库里面查询, 取出所有的 ThreadID,
2, 根据 ThreadID 构造 ForumThread 对象,
3, 返回一个数组.
}
|
这样做最省事, 最简单了, 但好不好呢? 还得看需求, 比如我要求根据时间排序,就还得修改这个方法, 也就是说需要修改 DbForum 对象. 那为什么不把取 Thread 这个操作单独拿出来呢? 这样的好处就是功能独立化, 使 DbForum 更简单, 符合前面我们所提到的不要让对象负担太多的责任这个原则. 也许你会说, 如果要修改的话, 不是都得修改吗? 放哪里是一样的, 这样没错, 但只限于很小的系统, 如果系统一大, 那么就可能做 DbForum 中的简单查询和一些比较复杂的查询的程序员就不是一个人, 这样牵扯到需要改动的地方较多, 但分离以后, 只需要一个人改很少的地方就可以完成. 回过头来再看看问题, 这里要返回一群 ForumThread 对象, 而且它们之间还可能有一定的先后关系, 怎么来做这个工作呢? Iterator 设计模式是一个合适的选择. Iterator 模式提供了一个连续访问一大群对象的方法, 而不需要知道它们的表现形式, 比如按什么方式排序等等. 好了, 来看看 Jive 的具体实现. 由于 Java 本身已经有这样的接口, Iterator 接口, 所以只要实现这个接口就可以了。
From DbForum:
public Iterator threads() {
return new DbForumIterator(this, factory);
}
From DbForumIterator: (做了改动)
public class DbForumIterator implements Iterator {
public DbForumIterator(...)
{
...
}
public boolean hasNext() //是否还有元素
{
...
}
public Object next() // 得到下一个元素
{
...
}
...
}
|
那么 jsp 中可以这样访问:
Iterator threads = aForum.threads();
while (threads.hasNext())
{
ForumThread thread = (ForumThread)threads.next();
做一些操作.
}
|
从中可以看出, 通过使用 Iterator 把 Threads 的一些具体细节进行了封装, 提供统一的接口. Jive 中这个设计模式也是用的非常多, 多个用户显示, 多个版面显示, 多个线索, 多个贴子都需要由它来实现.
小结
上面我们一起探讨了一下设计模式在 Jive 中的应用情况, 当然只是很简单, 很肤浅, 也很片面, 不过总算能对设计模式有些认识. 实际上, 设计模式就是吸收许多前人的经验, 把设计中一些重要的和重复出现的一些模式总结起来, 给出一个系统的命名,给出相应的解释和评价, 这个工作最先由 4 位软件大师所做, 他们合写了一本书 --Design Pattern: Elements of Reusable Object-Oriented Software, 后来, 人们把他们称为 GoF (Gang Of Four).
对于设计模式, 可能在我们的实际项目中自觉不自觉地在使用着, 比如 Factory Method 模式, Abstract 模式, Singleton 模式, Iterator 模式, 等等, 只是概念不是非的明确, 设计可能还有不太合理的地方, 处于一种跟着感觉走的状态, 相信很多有经验的设计者, 原来没有接触设计模式, 一旦接触以后, 会有一种恍然大悟的想法, 哈, 原来是这么回事. 学习设计模式, 能很好地帮助我们设计, 在相同的问题, 相同的背景下,可以直接使用它, 有的时候不知道该选择哪种好, 就需对问题进行更深一层的分析, 进行综合权衡, 对设计模式也要进行更深刻的理解, 才能得到好的结果, 这也是一个进步的过程.
对于笔者来说, 刚刚接触设计模式, 有了一点粗浅的理解, 就冒昧写了这篇算是一点心得的东西, 也是对自己的挑战, 中间犯的一些错误, 还请指正, 谢谢.
参考资料
- Design Pattern: Elements of Reusable Object-Oriented Software,
- Jive 源代码
关于作者
|
|
|
马旋 has authored this article
|
分享到:
相关推荐
以下是一些可能在JIVE论坛中运用的设计模式: 1. **单例模式**:在多线程环境下,如数据库连接池管理,确保全局只有一个实例存在,减少资源浪费,提高性能。在JIVE中,可能用于管理全局配置或缓存服务。 2. **工厂...
通过学习jive的源代码,开发者可以直观地看到这些设计模式在实际项目中的应用,从而提升自己的编程技能和架构设计能力。 jive作为一个开源的论坛系统,其代码库中包含了大量优秀的设计实践。例如,它使用了工厂模式...
本文主要围绕"Jive设计模式"展开,通过分析开源项目Jive的源代码,深入探讨设计模式在实际开发中的应用和价值。 Jive是一款开源的企业社交网络平台,它不仅提供了丰富的功能,还展示了优秀的软件架构和设计模式。...
Jive设计模式集合(中文) 详细的介绍jive的学习资源,想修炼code内功的就要好好研究设计模式,而jive是学习设计模式最好的例子。里面还有工具的连接向导,方便实用。如果你觉得好,给个好评!
jive学习源码学习,前一阵下载别人的不能用,传一个好使的.希望对奋斗在IT前线的同志们能有所帮助...系统设计,设计模式,数据库设计,权限设计,缓存系统,源代码研究,扩展功能,国际化支持,全文搜索,安全认证……
Jive 设计模式Jive 设计模式Jive 设计模式
Jive论坛是一款著名的开源社区软件,其源码中蕴含了丰富的设计模式应用,是学习和研究软件设计思想的宝贵资源。设计模式是软件工程中经过实践证明的有效解决方案,它们提供了一种在特定场景下解决常见问题的标准模板...
### 设计模式与Jive:面向对象编程的艺术 #### 前言 设计模式作为面向对象编程中的核心概念之一,不仅是提升程序员技能的关键,也是迈向高级程序员道路上的必经之路。《Design Patterns in Action》这本书深入浅出...
首先,Jive的源码中可能会包含以下经典设计模式: 1. **单例模式(Singleton)**:用于确保一个类只有一个实例,并提供全局访问点。在Jive中,可能会用到单例来管理某些系统级的服务或者资源,例如数据库连接池或...
在Jive源码中,我们可以看到许多经典的设计模式,如单例模式、工厂模式、观察者模式、装饰器模式和策略模式等。例如,单例模式在全局配置或线程池管理中广泛应用,保证了在整个系统中只有一个实例存在;工厂模式用于...
除此之外,Jive源码还可能包含命令模式、策略模式、状态模式等多种设计模式,这些都是软件设计中的重要工具。通过深入学习和分析这些模式在实际项目中的应用,我们可以提升代码的可读性、可维护性和可复用性,从而...
Jive模式,即在Jive这个开源论坛项目中应用的设计模式,为我们提供了一个在实际项目中运用设计模式的例子。 Jive是一款基于JSP技术的开源论坛系统,它的设计思想简洁而高效,适用于中小型网站构建论坛。设计模式...
jive forums 设计模式 Version: 3.2.9 Below is a list of known issues affecting this release of Jive Forums (3.2.9).
2.设计模式是比 J2EE 等框架软件更小的体系结构,J2EE 中许多具体程序都是应用设计模式来完成的,当你深入到 J2EE 的内 部代码研究时,这点尤其明显,因此,如果你不具备设计模式的基础知识(GoF 的设计模式),你很难...
转自jdon论坛 主要通过对jive论坛的分析阐述了设计模式
通过研究Jive论坛的源代码,我们可以深入了解JAVA在大型社区应用中的实际运用,以及如何运用设计模式来构建可扩展、易维护的系统。 首先,让我们关注“Jive论坛”的核心功能。Jive论坛主要由用户管理、论坛版块、...
- **设计模式变通**:Jive在应用设计模式时并没有完全遵循《设计模式:可复用面向对象软件的基础》(Gang of Four, GOF)中的实现方式,而是根据实际需求进行了适当的调整。 - **面向接口编程**:这种模式不仅提高了...
本文将从两个主要方面来深入剖析Jive:功能需求和技术实现中的设计模式应用。 #### 功能需求分析 Jive作为一个成熟的论坛系统,在设计之初就充分考虑了用户的需求和使用体验。其核心功能包括但不限于: 1. **用户...