觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象,主體對象的狀態變化會通知所有觀察者對象。觀察者模式又叫做發布-訂閱模式、模型-視圖模式、源-監聽器模式或從屬者模式。這種模式在我們實際生活中並不鮮見,比如訂牛奶、訂報紙。我們訂閱了某報紙之后,一旦報紙有新版出來,就會送到我們報箱或手中,去過取消訂閱,那么也就再也收不到了。有了互聯網之后,無論是微博好友還是微信訂閱號,我們都可以“關注”和“取消關注”,關注了就可以收到信息推動。這些都是觀察者模式的現實體現。
而今天我給大家介紹一下在微信訂閱號的關注和消息推送中觀察者模式的應用。
在微信的訂閱號中,訂閱號可以被關注或取消關注,當有新的文章、消息、出現的時候,訂閱了的讀者都會收到消息。所以可以抽象出來一個共同的抽象類Publisher
來實現這些公共的方法。
public abstract class Publisher { private List<Subscriber> funs = new ArrayList<Subscriber>(); private String message; public void publishMessage(String message) { this.message = message; notifyAllSubscribers(); } public String getMessage() { return message; } public void addSubscriber(Subscriber subscriber) { funs.add(subscriber); } public void delSubscriber(Subscriber subscriber) { funs.remove(subscriber); } public void notifyAllSubscribers() { Iterator<Subscriber> it = funs.iterator(); while (it.hasNext()) { it.next().update(this); } } }
Publisher
維護有一個訂閱者的集合,其中message
統一表示文章、信息或聲音作品等各種形式的內容,由publishMessage
更新內容,而當有新的內容更新時,會調用notifyAllSubscibers
方法來通知所有關注人。這里要注意的是,這種通知是一種回調行為,也就是通過遍歷並調用各個subscriber
的update
方法來進行通知。
public interface Subscriber { void update(Publisher publisher); }
因此,具體來說,微信訂閱號就是一種Publisher。
public class WeixinPublisher extends Publisher { private String dingyuehao; public WeixinPublisher(String dingyuehao) { this.dingyuehao = dingyuehao; } @Override public String toString() { return "微信訂閱號[" + dingyuehao + "]"; } }
而普通的微信用戶——即關注者——就是Subscriber。
public class WeixinAccount implements Subscriber { private String accountName; public WeixinAccount(String accountName) { this.accountName = accountName; } public void update(Publisher publisher) { System.out.println(accountName + "的微信收到了來自" + publisher + "的推送文章: " + publisher.getMessage()); } }
微信用戶實現了具體的update方法,定義了在收到通知后要做哪些操作,比如閱讀、轉發等等,這里通過打印一行文字來表示。
public class Client { public static void main(String[] args) { WeixinPublisher publisher = new WeixinPublisher("享學IT"); publisher.addSubscriber(new WeixinAccount("張三")); publisher.addSubscriber(new WeixinAccount("李四")); publisher.addSubscriber(new WeixinAccount("王五")); publisher.publishMessage("Java設計模式百例-觀察者模式"); } }
例如,張三執行“關注”操作后,微信訂閱號執行addSubscriber操作將他添加到自己的訂閱者名單中,當發布新消息時,訂閱者都可以收到,輸出如下。
張三的微信收到了來自微信訂閱號[享學IT]的推送文章: Java設計模式百例-觀察者模式
最后,用一個類圖看一下類和接口關系就比較清晰了。
從中可以總結出幾個觀察者模式的特點:
1.觀察者模式是一個一對多的關系,一個被觀察者對應多個觀察者,這種關系通過在被觀察者內維護一個觀察者的集合來實現。
2.但是與“被圍觀”不同的是,被觀察者擁有添加和刪除觀察者的方法,主動權在自己手中。
3.當被觀察者狀態有變動時,也是由被觀察者主動通知自己維護的“名單”中的各個觀察者,通知是采用回調接口方法的方式。
在java中內置了觀察者模式的接口和抽象類Observable.java。其中包含了上訴Publisher類中的各個方法,所以就不用自己寫了,可以直接使用Observable。它的使用模式與微信訂閱號的關注和消息推送中的觀察者模式很相似。
本文源碼見:https://github.com/get-set/get-designpatterns/tree/master/observer