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