Board logo

标题: Jive 源代码研究(1) [打印本页]

作者: look_w    时间: 2018-7-11 08:37     标题: Jive 源代码研究(1)

前言 Jive 是一个开放的 Java 源代码项目。其目标是建设一个开放结构的,强壮的,易于扩展的基于 JSP 的论坛。在其设计目标的指导下,其结构设计得非常得好,融合了很多新的观念,比如 Design  Pattern,可更换的 Skin,可插入 Plug 等等。详细解读其源代码对于理解这些新的设计上的概念是很有裨益的。如果你对 Design  Pattern 和 Java 语言有一定的了解,但是还是会时常迷惑于其中的话,不妨研究研究 Jive 源代码,一定会对其中的很多概念有更深入的理解。这篇文章源于我的 Jive 源代码研究笔记,希望能够提纲挈领,带领大家进入到这个美好的世界。当然,如果没有时间仔细地看源代码的话,看看这篇文章,我想也是会有一些帮助的。
再开始之前,需要指出的是,Jive 中对 Design  Pattern 的应用,并没有拘礼与 GOF 书中所给出的实现方法,而是有许多变通的地方。一方面,我想是由于具体的实际需要,另一方面,我想这也是设计观念进化的结果吧。因而,这些变通的地方,将是我讲解的重点。
整体结构概叙基于一个 OO 的设计原则:面向接口编程,而不是针对实现编程。Jive 在设计的时候,把其大部分的基本对象都设计为接口或者抽象类。在 Jive 中,基本的接口有 Forum,ForumMessage,ForumThread,Group,User,Authorization 和 Query。我们可以很容易的从这些接口的名字来知道他们的功用,下面的类图给出了这些类之间的一些静态关系:
图 1:Jive 整体关系你可能会有疑问,为什么会都是接口呢?这是基于扩展性考虑的。在 Jive 给出的实现中,所有的这些接口,Forum,ForumMessage,User 等等,都使用数据库来实现的,一条消息,或者一个用户对应于数据库中的一条消息 Jive 使用了 DbForum,DbForumMessage,DbUser 等类来实现这些接口,通过 JDBC 来操作数据库,使之作为论坛的底层支撑。
然而,有时候,或许我们并不想使用数据库,比如我们想只是使用文件系统来作为论坛的底层支撑,这时候,我们需要做的只是编码实现了 Forum 等等接口的诸如 FileFroum,FileForumMessage 等对象,然后嵌入 Jive 中即可,原有的任何代码都可以不用改变!!!这就是面向接口编程的威力了!
下面来看看具体的设计和编码。
AbstractFactory 模式和可扩展性如果要实现较好的可扩展性,AbstractFactory 模式确实是一件利器。如上面所说,如果要创建的 Forum 接口的不同实现,而又不想更改代码的话,就需要用到抽象工厂了。再 Jive 中,AuthorizationFactory 类是一个抽象类,用来创建 Authorization 对象。这是一个抽象工厂,可以通过不同的子类来创建不同的 Authorization 对象。这个工厂的实现方法是:
在 AuthorizationFactory 中使用一个 private  static 变量 factory,用来引用具体的抽象工厂的实例:        
private static AuthorizationFactory factory =  null;
用一个 private  static 的 String,来指明具体的抽象工厂的子类类名:        
private static String className  ="com.coolservlets.forum.database.DbAuthorizationFactory";
然后是用一个 private  static 的 loadAuthorizationFactory 方法来给这个 factory 变量赋值,生成具体的抽象工厂类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static void loadAuthorizationFactory() {
       if (factory == null) {
           synchronized(className) {
               if (factory == null) {
                   String classNameProp = PropertyManager.getProperty(
                       "AuthorizationFactory.className"
                   );
                   if (classNameProp != null) {
                       className = classNameProp;
                   }
                   try {
                       Class c = Class.forName(className);
                       factory = (AuthorizationFactory)c.newInstance();
                   }
                   catch (Exception e) {
                       System.err.println("Exception loading class: " + e);
                       e.printStackTrace();
                   }
               }
           }
       }
}




在 static 的 getAuthorization 方法返回一个 Authorization 的过程中,先初始化工厂类 factory 变量,然后用 factory 的 createAuthorization 方法来创建:
1
2
3
4
5
6
public static Authorization getAuthorization(String username,
           String password) throws UnauthorizedException
   {
       loadAuthorizationFactory();
       return factory.createAuthorization(username, password);
}




不同的子类有不同的 createAuthorization 方法的实现。比如在 DbAuthorizationFactory 这个 AuthorizationFactory 的数据库实现子类中,createAuthorization 方法是这样实现的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public Authorization createAuthorization(String username, String password)
          throws UnauthorizedException
  {
      if (username == null || password == null) {
          throw new UnauthorizedException();
      }
      password = StringUtils.hash(password);
      int userID = 0;
      Connection con = null;
      PreparedStatement pstmt = null;
      try {
          con = DbConnectionManager.getConnection();
          pstmt = con.prepareStatement(AUTHORIZE);
          pstmt.setString(1, username);
          pstmt.setString(2, password);
          ResultSet rs = pstmt.executeQuery();
          if (!rs.next()) {
              throw new UnauthorizedException();
          }
          userID = rs.getInt(1);
      }
      catch( SQLException sqle ) {
          System.err.println("Exception in DbAuthorizationFactory:" + sqle);
          sqle.printStackTrace();
          throw new UnauthorizedException();
      }
      finally {
          try {  pstmt.close(); }
          catch (Exception e) { e.printStackTrace(); }
          try {  con.close();   }
          catch (Exception e) { e.printStackTrace(); }
      }
      return new DbAuthorization(userID);
  }




在这个类中,可以看到抽象类和具体的子类之间的关系,它们是如何协作的,又是如何划分抽象方法和非抽象方法的,这都是值得注意的地方。一般的,抽象方法需要子类来实现,而抽象类中的非抽象方法应该所有子类所能够共享的,或者可是说,是定义在抽象方法之上的较高层的方法。这确实是一个抽象工厂的好例子!虽然实现的方法已经和 GOF 中给出的实现相差较远了,但思想没变,这儿的实现,也确实是要巧妙的些。
还有就是静态方法的使用,使得这个类看起来有些 Singleton 的意味。这使得对于 AbstractFactory 的创建变得简单。
下面的类图给出了这个 AbstractFactory 的实现的总体情况:
图 2:AbstractFactory 模式的实现类图在 AuthorizationFactory 中定义的其它方法,涉及到具体的如何创建 Authorization,都是作为 abstract 方法出现,具体实现留给子类来完成。
这样,在需要生成一个 Authorization 的时候,只需要调用 AuthorizationFactory 的静态方法 getAuthorization 就可以了,由子类实现了具体的细节。
其它的,如同上面讲到的,在创建 Forum 的时候用的 ForumFactory,具有同上面一样的实现,这就是模式之所以称为模式的所在了。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0