什么是觀察者模式(Observer Pattern)
觀察者模式定義了對象之間的一對多依賴。這樣一來焦读,當一個對象狀態(tài)改變時它的所有依賴者都會收到通知并自動更新。
觀察者模式的應(yīng)用
觀察者模式的應(yīng)用很廣泛。例如在Android開發(fā)時需要對控件注冊事件監(jiān)聽创淡,控件屬于被觀察者另绩,在該控件上所注冊的事件屬于觀察者儒陨,當控件發(fā)生變化時相應(yīng)的監(jiān)聽事件會立即做出回應(yīng)。我想大家都有自己喜歡的微信公眾號笋籽,其實微信公眾號的訂閱蹦漠、推送很好的體現(xiàn)了觀察者模式。當我們想及時獲得自己喜歡的公號的更新就得先關(guān)注它车海,然后公號有更新時會第一時間通知它的每一位仰慕者笛园。
設(shè)計模式來源于生活,細細品味生活能夠更好的去理解設(shè)計模式侍芝。
觀察者模式所涉及的 OO 設(shè)計原則
實現(xiàn)交互對象之間的松耦合研铆。
何為對象之間的松耦合?松耦合就是兩個對象可以交互州叠,但是不太清楚彼此的細節(jié)棵红。更通俗一點來說就是你和你的手機就是松耦合的,你可以很輕松的玩耍你的手機(你和手機進行者交互)咧栗,但你并知道手機內(nèi)部的實現(xiàn)逆甜,手機也更不知道使用者是誰啦。
封裝變化致板。
多用組合交煞,少用繼承。
針對接口編程斟或,不針對實現(xiàn)編程素征。
觀察者模式 Java 代碼實現(xiàn)及分析
分析
此 Demo 借用模擬微信公眾號簡單地實現(xiàn)了觀察者模式。
WeChatPublicNumber 是所有微信公眾號的公共接口萝挤,所有具體的微信公眾號都要實現(xiàn)此接口御毅,CnboJavaDev 就是一個實現(xiàn)此接口的微信公眾號(我決定了,我以后的微信公眾號就叫此名了怜珍,嘻嘻)亚享。WeChatPublicNumber 提供了用戶訂閱 registerUser(User user) 和取消訂閱的方法 removeUser(User user),還有推送更新的方法 notifyUsers()绘面。
User 是所有用戶的公共接口欺税,此接口提供了更新方法 update() 和文章閱讀方法 readArticle() (此方法主要用來測試打印)侈沪。Facebook 和 Google 實現(xiàn)了 User 接口。
TestObserver 用于對此 Demo 的測試晚凿。
Demo 的 UML 類圖
- WeChatPublicNumber.java
/**
* WeChatPublicNumber(微信公眾號接口)
* @author cnbo
*/
public interface WeChatPublicNumber {
//用戶訂閱公號
public void registerUser(User user);
//用戶取消訂閱
public void removeUser(User user);
//向所有訂閱用戶推送更新
public void notifyUsers();
}
- Article.java
/**
* 文章(別亂想哦)
* @author cnbo
*
*/
public class Article {
/** 文章的標題 */
private String title;
/** 文章的作者 */
private String author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "title:" + title + "; author:" + author;
}
}
- User.java
/**
* 微信用戶接口
* @author cnbo
*
*/
public interface User {
public void update(Article article);
public void readAritcle();
}
- CnboJavaDev.java
/**
* CnboJavaDev是一個實現(xiàn)了接口WeChatPublicNumber
* 的具體的公號
* @author cnbo
*/
public class CnboJavaDev implements WeChatPublicNumber {
private Article article;
private List<User> users;
public CnboJavaDev() {
users = new ArrayList<>();
}
@Override
public void registerUser(User user) {
if (users != null) {
users.add(user);
}
}
@Override
public void removeUser(User user) {
if (users != null && users.contains(user)) {
users.remove(user);
}
}
//發(fā)布文章
public void publishArticle() {
notifyUsers();
}
//向所有訂閱者推送文章
@Override
public void notifyUsers() {
if (users == null) {
return;
}
for (User user : users) {
user.update(article);
user.readAritcle();
}
}
public void addArticle(Article article) {
this.article = article;
publishArticle();
}
}
- Facebook.java
/**
* 微信用戶Facebook
* @author cnbo
*
*/
public class Facebook implements User {
private Article article;
private WeChatPublicNumber weChatPublicNumber;
public Facebook(WeChatPublicNumber weChatPublicNumber) {
this.weChatPublicNumber = weChatPublicNumber;
weChatPublicNumber.registerUser(this);
}
@Override
public void update(Article article) {
this.article = article;
}
@Override
public void readAritcle() {
System.out.println("facebook read " + article);
}
}
- Google.java
/**
* 微信用戶Google
* @author cnbo
*/
public class Google implements User {
private Article article;
private WeChatPublicNumber weChatPublicNumber;
public Google(WeChatPublicNumber weChatPublicNumber) {
this.weChatPublicNumber = weChatPublicNumber;
weChatPublicNumber.registerUser(this);
}
@Override
public void update(Article article) {
this.article = article;
}
@Override
public void readAritcle() {
System.out.println("google read " + article);
}
}
- TestObserver.java
/*
* 測試觀察者模式
* @author cnbo
*/
public class TestObserver {
public static void main(String[] args) {
CnboJavaDev cnboJavaDev = new CnboJavaDev();
//facebook和google關(guān)注了cnboJavaDev(如果我真被facebook和google
//關(guān)注了亭罪,那我會興奮成神經(jīng)的,哈哈)
User facebook = new Facebook(cnboJavaDev);
User google = new Google(cnboJavaDev);
Article article1 = getArticle("學習筆記之單例設(shè)計模式", "cnbo");
//cnboJavaDev發(fā)布一篇新文章article1歼秽,同時facebook和google
//都接收到了更新应役,然后他哥倆有滋有味的讀者cnbo的文章。
cnboJavaDev.addArticle(article1);
Article article2 = getArticle("學習筆記之策略設(shè)計模式", "cnbo");
cnboJavaDev.addArticle(article2);
}
public static Article getArticle(String title, String author) {
Article article = new Article();
article.setTitle(title);
article.setAuthor(author);
return article;
}
}