原創做品,能夠轉載,可是請標註出處地址:http://www.cnblogs.com/V1haoge/p/6513651.htmlhtml
觀察者模式,又能夠稱之爲發佈-訂閱模式,觀察者,顧名思義,就是一個監聽者,相似監聽器的存在,一旦被觀察/監聽的目標發生的狀況,就會被監聽者發現,這麼想來目標發生狀況到觀察者知道狀況,實際上是由目標將狀況發送到觀察者的。java
觀察者模式多用於實現訂閱功能的場景,例如微博的訂閱,當咱們訂閱了某我的的微博帳號,當這我的發佈了新的消息,就會通知咱們。設計模式
如今咱們舉一個相似的狀況,並使用代碼來實現,爲你們提供一個比較明顯的認識。ide
警察在找到嫌犯的時候,爲了找到幕後主使,通常都會蹲點監察,這裏我有三名便衣警察來蹲點監察2名嫌犯,三名便衣分別是:張昊天、石破天、趙日天,兩名嫌犯是:大熊與黑狗,詳見代碼:測試
觀察者接口:Observer編碼
1 public interface Observer { 2 void update(String message,String name); 3 }
定義三名便衣觀察者:Bianyi一、Bianyi二、Bianyi3spa
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 }
定義兩個嫌疑犯:XianFan一、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 }
測試類:Clientercode
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)定義通知方法,用於將新狀況通知給觀察者用戶(訂閱者用戶)
三、觀察者中須要有個接收被觀察者通知的方法。
如此而已!
觀察者模式定義的是一對多的依賴關係,一個被觀察者能夠擁有多個觀察者,而且經過接口對觀察者與被觀察者進行邏輯解耦,下降兩者的直接耦合。
如此這般,想了一番以後,忽然發現這種模式與橋接模式有點相似的感受。
橋接模式也是擁有雙方,一樣是使用接口(抽象類)的方式進行解耦,使雙方可以無限擴展而互不影響,其實兩者仍是有者明顯的區別:
一、主要就是使用場景不一樣,橋接模式主要用於實現抽象與實現的解耦,主要目的也正是如此,爲了雙方的自由擴展而進行解耦,這是一種多對多的場景。觀察者模式側重於另外一方面的解耦,側重於監聽方面,側重於一對多的狀況,側重於一方發生狀況,多方能得到這個狀況的場景。
二、另外一方面就是編碼方面的不一樣,在觀察者模式中存在許多獨有的內容,如觀察者集合的操做,通知的發送與接收,而在橋接模式中只是簡單的接口引用。
同系列文章: