天天看點

Java設計模式之《觀察者模式》及應用場景

原創作品,可以轉載,但是請标注出處位址:http://www.cnblogs.com/V1haoge/p/6513651.html

  觀察者模式,又可以稱之為釋出-訂閱模式,觀察者,顧名思義,就是一個監聽者,類似監聽器的存在,一旦被觀察/監聽的目标發生的情況,就會被監聽者發現,這麼想來目标發生情況到觀察者知道情況,其實是由目标将情況發送到觀察者的。

  觀察者模式多用于實作訂閱功能的場景,例如微網誌的訂閱,當我們訂閱了某個人的微網誌賬号,當這個人釋出了新的消息,就會通知我們。

  現在我們舉一個類似的情況,并使用代碼來實作,為大家提供一個比較明顯的認識。

  警察在找到嫌犯的時候,為了找到幕後主使,一般都會蹲點監察,這裡我有三名便衣警察來蹲點監察2名嫌犯,三名便衣分别是:張昊天、石破天、趙日天,兩名嫌犯是:大熊與黑狗,詳見代碼:

觀察者接口:Observer

1 public interface Observer {
2     void update(String message,String name);
3 }      

定義三名便衣觀察者:Bianyi1、Bianyi2、Bianyi3

1 /**
 2  * 便衣警察張昊天
 3  */
 4 public class Bianyi1 implements Observer {
 5     //定義姓名
 6     private String bname = "張昊天";
 7     @Override
 8     public void update(String message,String name) {
 9         System.out.println(bname+":"+name+"那裡有新情況:"+ message);
10     }
11 }
12 
13 /**
14  * 便衣警察石破天
15  */
16 public class Bianyi2 implements Observer {
17     //定義姓名
18     private String bname = "石破天";
19     @Override
20     public void update(String message,String name) {
21         System.out.println(bname+":"+name+"那裡有新情況:"+ message);
22     }
23 }
24 
25 /**
26  * 便衣警察趙日天
27  */
28 public class Bianyi3 implements Observer {
29     //定義姓名
30     private String bname = "趙日天";
31     @Override
32     public void update(String message,String name) {
33         System.out.println(bname+":"+name+"那裡有新情況:"+ message);
34     }
35 }      

目标接口:Huairen

1 public interface Huairen {
2     //添加便衣觀察者
3     void addObserver(Observer observer);
4     //移除便衣觀察者
5     void removeObserver(Observer observer);
6     //通知觀察者
7     void notice(String message);
8 }      

定義兩個嫌疑犯:XianFan1、XianFan2

1 import java.util.*;
 2 /**
 3  * 嫌犯大熊
 4  */
 5 public class XianFan1 implements Huairen {
 6     //别稱
 7     private String name = "大熊";
 8     //定義觀察者集合
 9     private List<Observer> observerList = new ArrayList<Observer>();
10     //增加觀察者
11     @Override
12     public void addObserver(Observer observer) {
13         if(!observerList.contains(observer)){
14             observerList.add(observer);
15         }
16     }
17     //移除觀察者
18     @Override
19     public void removeObserver(Observer observer) {
20         if(observerList.contains(observer)){
21             observerList.remove(observer);
22         }
23     }
24     //通知觀察者
25     @Override
26     public void notice(String message) {
27         for(Observer observer:observerList){
28             observer.update(message,name);
29         }
30     }
31 }
32 
33 import java.util.*;
34 /**
35  * 嫌犯黑狗
36  */
37 public class XianFan2 implements Huairen {
38     //别稱
39     private String name = "黑狗";
40     //定義觀察者集合
41     private List<Observer> observerList = new ArrayList<Observer>();
42     //增加觀察者
43     @Override
44     public void addObserver(Observer observer) {
45         if(!observerList.contains(observer)){
46             observerList.add(observer);
47         }
48     }
49     //移除觀察者
50     @Override
51     public void removeObserver(Observer observer) {
52         if(observerList.contains(observer)){
53             observerList.remove(observer);
54         }
55     }
56     //通知觀察者
57     @Override
58     public void notice(String message) {
59         for(Observer observer:observerList){
60             observer.update(message,name);
61         }
62     }
63 }      

測試類:Clienter

1 public class Clienter {
 2     public static void main(String[] args) {
 3         //定義兩個嫌犯
 4         Huairen xf1 = new XianFan1();
 5         Huairen xf2 = new XianFan2();
 6         //定義三個觀察便衣警察
 7         Observer o1 = new Bianyi1();
 8         Observer o2 = new Bianyi2();
 9         Observer o3 = new Bianyi3();
10         //為嫌犯增加觀察便衣
11         xf1.addObserver(o1);
12         xf1.addObserver(o2);
13         xf2.addObserver(o1);
14         xf2.addObserver(o3);
15         //定義嫌犯1的情況
16         String message1 = "又賣了一批貨";
17         String message2 = "老大要下來視察了";
18         xf1.notice(message1);
19         xf2.notice(message2);
20     }
21 }      

測試結果:

張昊天:大熊那裡有新情況:又賣了一批貨
石破天:大熊那裡有新情況:又賣了一批貨
張昊天:黑狗那裡有新情況:老大要下來視察了
包拯:黑狗那裡有新情況:老大要下來視察了      

  通過上面的執行個體可以很明顯的看出,觀察者模式的大概模型,關鍵是什麼呢?

  關鍵點:

    1、針對觀察者與被觀察者分别定義接口,有利于分别進行擴充。

    2、重點就在被觀察者的實作中:

      (1)定義觀察者集合,并定義針對集合的添加、删除操作,用于增加、删除訂閱者(觀察者)

      (2)定義通知方法,用于将新情況通知給觀察者使用者(訂閱者使用者)

    3、觀察者中需要有個接收被觀察者通知的方法。

  如此而已!

  觀察者模式定義的是一對多的依賴關系,一個被觀察者可以擁有多個觀察者,并且通過接口對觀察者與被觀察者進行邏輯解耦,降低二者的直接耦合。

  如此這般,想了一番之後,突然發現這種模式與橋接模式有點類似的感覺。

  橋接模式也是擁有雙方,同樣是使用接口(抽象類)的方式進行解耦,使雙方能夠無限擴充而互不影響,其實二者還是有者明顯的差別:

    1、主要就是使用場景不同,橋接模式主要用于實作抽象與實作的解耦,主要目的也正是如此,為了雙方的自由擴充而進行解耦,這是一種多對多的場景。觀察者模式側重于另一方面的解耦,側重于監聽方面,側重于一對多的情況,側重于一方發生情況,多方能獲得這個情況的場景。

    2、另一方面就是編碼方面的不同,在觀察者模式中存在許多獨有的内容,如觀察者集合的操作,通知的發送與接收,而在橋接模式中隻是簡單的接口引用。

同系列文章:

  • Java設計模式之《擴充卡模式》及應用場景
  • Java設計模式之《外觀模式》及應用場景
  • Java設計模式之《橋接模式》及應用場景
  • Java設計模式之《單例模式》及應用場景
  • Java設計模式之《觀察者模式》及應用場景
  • Java設計模式之《調停者模式》及應用場景
  • Java設計模式之《代理模式》及應用場景
  • Java設計模式之《職責鍊模式》及應用場景
  • Java設計模式之《享元模式》及應用場景
  • Java設計模式之《建構者模式》及應用場景
  • Java設計模式之《模闆模式》及使用場景
  • Java設計模式之《裝飾器模式》及應用場景
  • Java設計模式之《工廠方法模式》及使用場景
  • Java設計模式之《抽象工廠模式》及使用場景