以Java設計模式中的觀察者模式開發微信公眾號的實例程式碼

高洛峰
發布: 2017-03-28 14:20:33
原創
1819 人瀏覽過

這篇文章主要介紹了用Java設計模式中的觀察者模式開發微信公眾號的例子,這裡Java的微信SDK等部分便不再詳述,只注重關鍵部分和開發過程中觀察者模式優點的體現,需要的朋友可以參考下

還記得警匪片上,匪徒們是怎麼配合實施犯罪的嗎?一個團夥在進行盜竊的時候,總有一兩個人在門口把風——如果有什麼風吹草動,則會立即通知裡面的同夥緊急撤退。也許放風的人不一定認識裡面的每一個同夥;而在裡面也許有新來的小弟不認識這個放風的。但這沒什麼,這個影響不了他們之間的通訊,因為他們之間有早已商定好的暗號。
呵呵,上述的放風者、偷竊者之間的關係就是觀察者模式在現實中的活生生的例子。

觀察者(Observer)模式又稱為發布-訂閱(Publish/Subscribe)模式。 GOF給觀察者模式如下定義:定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴它的物件都會得到通知並被自動更新。
在這裡先講一下物件導向設計的一個重要原則-單一職責原則。因此系統的每個物件應該將重點放在問題域中的離散抽像上。因此理想的情況下,一個物件只做一件事情。這樣在開發中也帶來了許多的好處:提供了重用性和維護性,也是進行重構的良好的基礎。
因此幾乎所有的設計模式都是基於這個基本的設計原則來的。觀察者模式的起源我覺得應該是在GUI和業務資料的處理上,因為現在絕大多數講解觀察者模式的例子都是這一題材。但是觀察者模式的應用絕不僅限於此一方面。


好了,對於定義的理解總是需要實例來解析的,如今的微信服務號相當火啊,下面就以微信服務號為背景,給大家介紹觀察者模式。
看一張圖:

以Java設計模式中的觀察者模式開發微信公眾號的實例程式碼

其中每個使用者都有上圖中的3條線,為了讓圖片清晰省略了。
如上圖所示,服務號碼就是我們的主題,使用者就是觀察者。現在我們明確下功能:
1、服務號碼就是主題,業務就是推播訊息
2、觀察者只需要訂閱主題,只要有新的訊息就會送來
3、當不要此主題訊息時,取消訂閱
4、只要服務號碼還在,就會一直有人訂閱
好了,現在我們來看看觀察者模式的類別圖:

以Java設計模式中的觀察者模式開發微信公眾號的實例程式碼

接下來就是程式碼時間了,我們模擬一個微信3D彩票服務號,和一些訂閱者。
首先開始寫我們的主題介面,和觀察者介面:

package com.zhy.pattern.observer; 
 
/** 
 * 主题接口,所有的主题必须实现此接口 
 * 
 * @author zhy 
 * 
 */ 
public interface Subject 
{ 
  /** 
   * 注册一个观察着 
   * 
   * @param observer 
   */ 
  public void registerObserver(Observer observer); 
 
  /** 
   * 移除一个观察者 
   * 
   * @param observer 
   */ 
  public void removeObserver(Observer observer); 
 
  /** 
   * 通知所有的观察着 
   */ 
  public void notifyObservers(); 
 
} 
package com.zhy.pattern.observer; 
 
/** 
 * @author zhy 所有的观察者需要实现此接口 
 */ 
public interface Observer 
{ 
  public void update(String msg); 
 
}
登入後複製

接下來3D服務號碼的實作類別:

package com.zhy.pattern.observer; 
 
import java.util.ArrayList; 
import java.util.List; 
 
public class ObjectFor3D implements Subject 
{ 
  private List<observer> observers = new ArrayList<observer>(); 
  /** 
   * 3D彩票的号码 
   */ 
  private String msg; 
 
  @Override 
  public void registerObserver(Observer observer) 
  { 
    observers.add(observer); 
  } 
 
  @Override 
  public void removeObserver(Observer observer) 
  { 
    int index = observers.indexOf(observer); 
    if (index >= 0) 
    { 
      observers.remove(index); 
    } 
  } 
 
  @Override 
  public void notifyObservers() 
  { 
    for (Observer observer : observers) 
    { 
      observer.update(msg); 
    } 
  } 
 
  /** 
   * 主题更新消息 
   * 
   * @param msg 
   */ 
  public void setMsg(String msg) 
  { 
    this.msg = msg; 
     
    notifyObservers(); 
  } 
 
}</observer></observer>
登入後複製

模擬兩個使用者:

package com.zhy.pattern.observer; 
 
public class Observer1 implements Observer 
{ 
 
  private Subject subject; 
 
  public Observer1(Subject subject) 
  { 
    this.subject = subject; 
    subject.registerObserver(this); 
  } 
 
  @Override 
  public void update(String msg) 
  { 
    System.out.println("observer1 得到 3D 号码 -->" + msg + ", 我要记下来。"); 
  } 
 
}
登入後複製
package com.zhy.pattern.observer; 
 
public class Observer2 implements Observer 
{ 
  private Subject subject ;  
   
  public Observer2(Subject subject) 
  { 
    this.subject = subject ; 
    subject.registerObserver(this); 
  } 
   
  @Override 
  public void update(String msg) 
  { 
    System.out.println("observer2 得到 3D 号码 -->" + msg + "我要告诉舍友们。"); 
  } 
   
   
 
}
登入後複製

可以看出:服務號碼中維護了所有向它訂閱訊息的使用者,當服務號碼有新訊息時,通知所有的使用者。整個架構是一種鬆散耦合,主題的實作不依賴與使用者,當增加新的使用者時,主題的程式碼不需要改變;使用者如何處理得到的資料與主題無關;
最後看下測試程式碼:

package com.zhy.pattern.observer.test; 
 
import com.zhy.pattern.observer.ObjectFor3D; 
import com.zhy.pattern.observer.Observer; 
import com.zhy.pattern.observer.Observer1; 
import com.zhy.pattern.observer.Observer2; 
import com.zhy.pattern.observer.Subject; 
 
public class Test 
{ 
  public static void main(String[] args) 
  { 
    //模拟一个3D的服务号 
    ObjectFor3D subjectFor3d = new ObjectFor3D(); 
    //客户1 
    Observer observer1 = new Observer1(subjectFor3d); 
    Observer observer2 = new Observer2(subjectFor3d); 
 
    subjectFor3d.setMsg("20140420的3D号码是:127" ); 
    subjectFor3d.setMsg("20140421的3D号码是:333" ); 
     
  } 
}
登入後複製

輸出結果:

observer1 得到 3D 号码 -->20140420的3D号码是:127, 我要记下来。 
observer2 得到 3D 号码 -->20140420的3D号码是:127我要告诉舍友们。 
observer1 得到 3D 号码 -->20140421的3D号码是:333, 我要记下来。 
observer2 得到 3D 号码 -->20140421的3D号码是:333我要告诉舍友们。
登入後複製

對於JDK或Andorid中都有很多地方實作了觀察者模式,例如XXXView.addXXXListenter , 當然了 XXXView.setOnXXXListener不一定是觀察者模式,因為觀察者模式是一種一對多的關係,對於setXXXListener是1對1的關係,應該叫回調。

恭喜你学会了观察者模式,上面的观察者模式使我们从无到有的写出,当然了java中已经帮我们实现了观察者模式,借助于java.util.Observable和java.util.Observer。
下面我们使用Java内置的类实现观察者模式:

首先是一个3D彩票服务号主题:

package com.zhy.pattern.observer.java; 
 
import java.util.Observable; 
 
public class SubjectFor3d extends Observable 
{ 
  private String msg ;  
   
   
  public String getMsg() 
  { 
    return msg; 
  } 
 
 
  /** 
   * 主题更新消息 
   * 
   * @param msg 
   */ 
  public void setMsg(String msg) 
  { 
    this.msg = msg ; 
    setChanged(); 
    notifyObservers(); 
  } 
}
登入後複製

下面是一个双色球的服务号主题:

package com.zhy.pattern.observer.java; 
 
import java.util.Observable; 
 
public class SubjectForSSQ extends Observable 
{ 
  private String msg ;  
   
   
  public String getMsg() 
  { 
    return msg; 
  } 
 
 
  /** 
   * 主题更新消息 
   * 
   * @param msg 
   */ 
  public void setMsg(String msg) 
  { 
    this.msg = msg ; 
    setChanged(); 
    notifyObservers(); 
  } 
}
登入後複製

最后是我们的使用者:

package com.zhy.pattern.observer.java; 
 
import java.util.Observable; 
import java.util.Observer; 
 
public class Observer1 implements Observer 
{ 
 
  public void registerSubject(Observable observable) 
  { 
    observable.addObserver(this); 
  } 
 
  @Override 
  public void update(Observable o, Object arg) 
  { 
    if (o instanceof SubjectFor3d) 
    { 
      SubjectFor3d subjectFor3d = (SubjectFor3d) o; 
      System.out.println("subjectFor3d's msg -- >" + subjectFor3d.getMsg()); 
    } 
 
    if (o instanceof SubjectForSSQ) 
    { 
      SubjectForSSQ subjectForSSQ = (SubjectForSSQ) o; 
      System.out.println("subjectForSSQ's msg -- >" + subjectForSSQ.getMsg()); 
    } 
  } 
}
登入後複製

看一个测试代码:

package com.zhy.pattern.observer.java; 
 
public class Test 
{ 
  public static void main(String[] args) 
  { 
    SubjectFor3d subjectFor3d = new SubjectFor3d() ; 
    SubjectForSSQ subjectForSSQ = new SubjectForSSQ() ; 
     
    Observer1 observer1 = new Observer1(); 
    observer1.registerSubject(subjectFor3d); 
    observer1.registerSubject(subjectForSSQ); 
     
     
    subjectFor3d.setMsg("hello 3d'nums : 110 "); 
    subjectForSSQ.setMsg("ssq'nums : 12,13,31,5,4,3 15"); 
     
  } 
}
登入後複製

测试结果:

subjectFor3d's msg -- >hello 3d'nums : 110  
subjectForSSQ's msg -- >ssq'nums : 12,13,31,5,4,3 15
登入後複製

可以看出,使用Java内置的类实现观察者模式,代码非常简洁,对了addObserver,removeObserver,notifyObservers都已经为我们实现了,所有可以看出Observable(主题)是一个类,而不是一个接口,基本上书上都对于Java的如此设计抱有反面的态度,觉得Java内置的观察者模式,违法了面向接口编程这个原则,但是如果转念想一想,的确你拿一个主题在这写观察者模式(我们自己的实现),接口的思想很好,但是如果现在继续添加很多个主题,每个主题的ddObserver,removeObserver,notifyObservers代码基本都是相同的吧,接口是无法实现代码复用的,而且也没有办法使用组合的模式实现这三个方法的复用,所以我觉得这里把这三个方法在类中实现是合理的。

以上是以Java設計模式中的觀察者模式開發微信公眾號的實例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!