原創作品,可以轉載,但是請标注出處位址: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設計模式之《抽象工廠模式》及使用場景