igaofen

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

(一)设计模式

LumaQQ采用MVC模式,这个模式基本上和我设计Xnews for GWZONE.com的时候那个模式是一模一样的,也就是我给大学城的师弟上培训课所说的模式,只是当时我还不知道这就是MVC模式。

MVC 模式分三层两部分,层级为表现层处理层数据层,两部分则是数据流输入输出,如下所示:

输入页面(View)----> Servlets controllers <----->商业数据(model)

输出页面(View)------>显示功能JSP(view engine)<---->商业数据(model,同上)

其中:Servlets controllers -------->显示功能JSP(view engine)

原图在《Java实用系统开发指南》P164。

ps, 原来实践得多了领悟出来的系统设计模式是会跟国际级大师们不谋而合的 (窃笑)

ps2, 按照我原来对面向对象程序设计的理解,主实体应该同时包含属性和行为,然而MVC模式规定了属性和行为必须分开放置,仅把属性捆绑到实体类内部,而把方法行为定义在实体类以外。类内的行为实质只是一些setter和getter,而不是实际的行为。这似乎有违面向对象的设计精神。

(二)事件触发分析(未完善)

(1)fire 行为

edu.tsinghua.lumaqq.qq 包内的BasicFamilyProcessor.java在processLoginReply行为内有这样一句注释:“// 登陆成功的话我们就设置用户的一些信息,然后触发事件”。这是一个switch体,以下是一个片断:

case QQ.QQ_LOGIN_REPLY_OK:

………… (这部分设置用户信息,形如user.setXxxx(zzzzzz))

// 触发事件
       e = new QQEvent(packet); // 猫注:初始化实例,packet是事件源对象,父类是Object
       e.type = QQEvent.QQ_LOGIN_SUCCESS; // 猫注:这东东是static的事件类型,int类型,实际上用于给public int type赋值。
       client.fireQQEvent(e); // 触发事件,e是一个QQ事件源,client就是当前QQ客户端的线程实体
       break;

(2)add listener 方法 和 fire 方法的定义

edu.tsinghua.lumaqq.qq 包内 QQClient.java 中implements IQQListener。定义添加监听器的方法如下:

// QQ监听器
    private List<IQQListener> qqListeners, qqListenersBackup; // 猫注:实际只用后者

…………

…………

public void addQQListener(IQQListener listener) {
     if(!qqListeners.contains(listener)) {  // 猫注:这是List的方法
      qqListeners.add(listener);  // 猫注:这是List的方法
      setListenerChanged(true);      
     }
    }

所以实际上添加监听器的方法只是向某List里添加一个对象元素而已。

以下是事件触发方法的定义:

/**
     * 触发QQ事件
     * @param e QQEvent
     */
    public void fireQQEvent(QQEvent e) {
     checkListenerChange();
  int size = qqListenersBackup.size();
  for(int i = 0; i < size; i++)
   qqListenersBackup.get(i).qqEvent(e); // 猫注:遍历所有监听器分别执行qqEvent行为,听起来好像比较笨
    }

(3)qqEvent 行为的定义

edu.tsinghua.lumaqq.ui 包内QQEventProcessor.java (implements IQQListener)。其中qqEvent行为方法实际是一个判断 e.type 的switch体:

public void qqEvent(QQEvent e) {
  switch(e.type) {
      case QQEvent.QQ_GET_LOGIN_TOKEN_FAIL:
          processLoginTimeout();
       break;
   case QQEvent.QQ_LOGIN_SUCCESS:
    processLoginSuccess();
    break; 
   case QQEvent.QQ_GET_FRIEND_ONLINE_SUCCESS:
    processGetFriendOnlineSuccess(e);
    break;

……

……

这样就完成了对响应事件的分类处理步骤。注意QQEvent里的属性都是static int的,之前有说明。

其中一个case用到了QQEvent的operation属性:

case QQEvent.QQ_OPERATION_TIMEOUT:
       switch(e.operation) {
           case QQ.QQ_CMD_LOGIN:
           case QQ.QQ_CMD_REQUEST_LOGIN_TOKEN:
      processLoginTimeout();
            break;
       }
    break;

用于判断事件源对应的是什么操作行为。

(4)使用add listener方法

edu.tsinghua.lumaqq.ui 包内 MainShell.java 首先定义了listener是啥东东:

// QQ事件处理器
    private QQEventProcessor processor;

然后把这东东add成一个listener,用的是QQ自己的add listener方法:

// 开始登陆
   btnStatus.startAnimate(loginFrames);
   processor.clear();
   client.addQQListener(processor);
   client.addQQListener(faceReceiver);

这里给客户端添加了两个监听器,一个是事件处理器,另一个是QQ表情接收器。

(5)分类事件处理的大致流程:

当client里有事件发生(fire)的时候,把事件传送到QQEventProcessor,再根据 e.type (fire的时候设置)分类处理事件。

posted on 2009-08-29 22:10  igaofen  阅读(294)  评论(0编辑  收藏  举报