麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即時聊天系統:9.觀察者模式

2019-11-15 00:10:15
字體:
來源:轉載
供稿:網友
【迷你微信】基于MINA、Hibernate、SPRing、Protobuf的即時聊天系統:9.觀察者模式

項目Logo歡迎閱讀我的開源項目《迷你微信》服務器與《迷你微信》客戶端

前言

在一個程序的迭代過程中,復雜度漸漸上升,可能會出現一些跨模塊的調用的需求,若是直接得到引用來進行使用,會導致模塊間的耦合度越來越高,消息機制是一種用于解耦這種耦合度高模塊的好方法,它的使用非常靈活便利,可以解決一對多(一個發送者,多個接受者)和需求頻繁的變更,甚至于,在添加新的需求時可以完全的不改動舊的代碼。在java中消息機制可以用觀察者模式來實現。

前緣未了

在【迷你微信】基于MINA、Hibernatye、Spring、Protobuf的即時聊天系統:7.項目介紹之架構中,我們說道了在發送聊天消息時,可能出現接受者不在線的情況,因為可能出現的各種復雜情況,封裝到我們將發送消息這個行為ServerModel_Chatting類中。

不知道大家有沒有注意到,微信的聊天消息是可能發送失敗的,也許因為網絡問題,也許因為對方根本沒有開啟微信,若是像登陸、注冊等請求,服務器向客戶端發包失敗,想偷懶的話,是可以不作處理的,不僅因為這種事件發生的幾率較少,也是因為這種異常的拋棄不會造成不可接受的后果,大不了再點擊一次登陸咯。但是,請想象一下,若是您的好友給您發了一條消息,因為您的一時網絡問題,服務器不能成功的發送給您,就將其直接拋棄,那么……您可能被您的友人認為是無視了他的消息,這種后果是不可接受的

所以,我們要對發送失敗的消息進行存儲,并在對方上線后及時的推送過去,這個模塊是比較復雜的,而且牽扯到復用(單聊、群聊)問題,還有存儲為永久數據問題,所以我們將其獨立成單獨的一個類來處理。在ServerModel_Chatting類的sendChatting方法中我們首先要從ServerModel中查找接受者是否在線,在線則可以直接推送;而不在線的情況下,則需要暫時存儲下來,等待接受者上線。

// 發送一條聊天消息public void sendChatting(final Chatting chattings) {ClientUser clientUser = serverModel.getClientUserByUserId(chattings.getReceiverUserId());// 如果不在線,則暫存if (clientUser == null){addChatting(chattings);return;}// 發送}// 暫存一條消息public void addChatting(Chatting chatting) {// 保存消息}

可以看到,發送聊天消息這個過程中,首先會判斷接受者是否在線,若是不在線會將消息暫存,在接受者上線后將接收到服務器推送的消息。然而,這個模塊如何知道接受者上線了呢?我們通過觀察者模式,在用戶登陸時通知本模塊進行查詢是否有為接收消息。

觀察者模式

觀察者模式中,首先要有被觀察者和觀察者兩個角色(可以有多個觀察者,俗稱”圍觀“(⊙o⊙)…),被觀察者要繼承Observable類,觀察者要對被觀察者對象調用addObserver 方法。

此處代碼皆為刪減版,欲查看完整代碼,請參考開源項目《迷你微信》服務器

先說說我們如何在用戶登陸時通知消息發送模塊進行查驗。1.在Server_User的 login方法中,用戶登陸成功時,會調用ServerModel的 clientUserLogin 方法,

public void clientUserLogin(ClientUser clientUser, String userId) {// 保存用戶信息clientUser.onLine = true;clientUser.userId = userId;clientUserIdTable.put(userId, clientUser);// 通知變更setChange();notifyObservers(new ObserverMessage_Login(clientUser.iosession, userId));}

在上面的方法中,我們將自己設置為變更狀態,然后通知所有觀察者。

2.觀察者ServerModel_Chatting添加監聽并進行處理

serverModel.addObserver(new Observer() {@Overridepublic void update(Observable o, Object arg) {ObserverMessage om = (ObserverMessage) arg;if (om.type == ObserverMessage.Type.Login) {// 發送登陸者未接收的消息}}}

在這里,我們對serverModel的實例化對象添加了一個監聽,判斷是否為監聽事件,若是,則發送未接收的消息。

后話

其實在本項目中,使用觀察者模式并不是一個好的做法,理由如下:

  • 被監聽者需要繼承Observable基類,在Java這種單繼承的語言中,這是不友好的。
  • 觀察者觀察到的消息需要每次都進行類型的判斷,針對性較差。
  • 觀察者需要得到被觀察者的引用才能添加觀察,耦合度沒有太大的減小。

因為帖主的這個項目中,目前只有這一個點需要用到這樣一種功能,所以偷了個懶。一旦需求復雜度提升,我們需要將觀察者模式做一些變化,將其做成完整的消息機制,使其具備一下幾個特點:

  • 消息發送者不需要繼承基類
  • 可以根據需要編寫不同的消息,接收者只需要注冊監聽指定的消息類型就可以接收到消息特定消息,而不是所有消息都接收。
  • 消息接收者不需要使用發送者的引用。

帖主的想法如下:

  • 首先,由使用者編寫各種消息MessageA, MessageB。
  • 有一個消息管理器MessageManager,其中擁有一個Hashtable>的哈希表對象,第一個參數是消息的類名(如MessageA),第二個鏈表參數是注冊監聽的所有監聽者。
  • 監聽者實現監聽接口,并將自己的引用和要注冊監聽的消息類型傳入MessageManager進行監聽。
  • 當消息被發送到MessageManager時,MessageManager會從Hashtable中取出注冊監聽的監聽者隊列,依次發送消息。

歡迎閱讀我的開源項目《迷你微信》服務器與《迷你微信》客戶端


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蜜桃一本色道久久综合亚洲精品冫 | 久久久久电影网站 | 成人三级在线播放 | 一级做受毛片免费大片 | 免费毛片播放 | 国产九九 | 最新毛片在线观看 | 久久久婷婷一区二区三区不卡 | 19禁国产精品福利视频 | 亚洲精品a级 | 久久精品一级片 | 巨根插入 | 欧美精品一区自拍a毛片在线视频 | 性欧美日本 | 欧美一级做性受免费大片免费 | 在线成人一区二区 | 国产亚洲精品综合一区91555 | 九九精品在线播放 | 国产无遮挡一区二区三区毛片日本 | 国产一区二区三区在线免费 | 草操影院| 免费a级毛片永久免费 | 激情小说图 | 久久sp| 久久精品亚洲成在人线av网址 | 国产999视频在线观看 | 国产二三区 | 中文字幕h | 国产一级毛片国语版 | 第四色成人网 | 欧美女同hd | 一级性生活视频 | 日本精品久久久久 | 精品亚洲夜色av98在线观看 | 久久在线| 国产一区二区精品免费 | 欧美××××黑人××性爽 | 国产亚洲精品久久久久久久久 | 亚洲国产在| 国产精品自拍片 | 欧美亚洲国产成人综合在线 |