設(shè)計(jì)模式筆記——觀察者模式

什么是觀察者模式(Observer Pattern)

觀察者模式定義了對(duì)象之間的一對(duì)多依賴。這樣一來,當(dāng)一個(gè)對(duì)象狀態(tài)改變時(shí)它的所有依賴者都會(huì)收到通知并自動(dòng)更新。

觀察者模式的應(yīng)用

觀察者模式的應(yīng)用很廣泛。例如在Android開發(fā)時(shí)需要對(duì)控件注冊(cè)事件監(jiān)聽,控件屬于被觀察者,在該控件上所注冊(cè)的事件屬于觀察者,當(dāng)控件發(fā)生變化時(shí)相應(yīng)的監(jiān)聽事件會(huì)立即做出回應(yīng)。我想大家都有自己喜歡的微信公眾號(hào),其實(shí)微信公眾號(hào)的訂閱、推送很好的體現(xiàn)了觀察者模式。當(dāng)我們想及時(shí)獲得自己喜歡的公號(hào)的更新就得先關(guān)注它,然后公號(hào)有更新時(shí)會(huì)第一時(shí)間通知它的每一位仰慕者。
設(shè)計(jì)模式來源于生活,細(xì)細(xì)品味生活能夠更好的去理解設(shè)計(jì)模式。

觀察者模式所涉及的 OO 設(shè)計(jì)原則

  • 實(shí)現(xiàn)交互對(duì)象之間的松耦合。

  • 何為對(duì)象之間的松耦合?松耦合就是兩個(gè)對(duì)象可以交互,但是不太清楚彼此的細(xì)節(jié)。更通俗一點(diǎn)來說就是你和你的手機(jī)就是松耦合的,你可以很輕松的玩耍你的手機(jī)(你和手機(jī)進(jìn)行者交互),但你并知道手機(jī)內(nèi)部的實(shí)現(xiàn),手機(jī)也更不知道使用者是誰啦。

  • 封裝變化。

  • 多用組合,少用繼承。

  • 針對(duì)接口編程,不針對(duì)實(shí)現(xiàn)編程。

觀察者模式 Java 代碼實(shí)現(xiàn)及分析

  • 分析

  • 此 Demo 借用模擬微信公眾號(hào)簡(jiǎn)單地實(shí)現(xiàn)了觀察者模式。

  • WeChatPublicNumber 是所有微信公眾號(hào)的公共接口,所有具體的微信公眾號(hào)都要實(shí)現(xiàn)此接口,CnboJavaDev 就是一個(gè)實(shí)現(xiàn)此接口的微信公眾號(hào)(我決定了,我以后的微信公眾號(hào)就叫此名了,嘻嘻)。WeChatPublicNumber 提供了用戶訂閱 registerUser(User user) 和取消訂閱的方法 removeUser(User user),還有推送更新的方法 notifyUsers()。

  • User 是所有用戶的公共接口,此接口提供了更新方法 update() 和文章閱讀方法 readArticle() (此方法主要用來測(cè)試打印)。Facebook 和 Google 實(shí)現(xiàn)了 User 接口。

  • TestObserver 用于對(duì)此 Demo 的測(cè)試。

  • Demo 的 UML 類圖

observer demo uml
  • WeChatPublicNumber.java
/**
 * WeChatPublicNumber(微信公眾號(hào)接口)
 * @author cnbo
 */
public interface WeChatPublicNumber {
    //用戶訂閱公號(hào)
    public void registerUser(User user);
    
    //用戶取消訂閱
    public void removeUser(User user);
    
    //向所有訂閱用戶推送更新
    public void notifyUsers();
}
  • Article.java
/**
 * 文章(別亂想哦)
 * @author cnbo
 * 
 */
public class Article {
    /** 文章的標(biāo)題 */
    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是一個(gè)實(shí)現(xiàn)了接口WeChatPublicNumber
 * 的具體的公號(hào)
 * @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
/*
 * 測(cè)試觀察者模式
 * @author cnbo
 */
public class TestObserver {
    public static void main(String[] args) {
        CnboJavaDev cnboJavaDev = new CnboJavaDev();
        //facebook和google關(guān)注了cnboJavaDev(如果我真被facebook和google
        //關(guān)注了,那我會(huì)興奮成神經(jīng)的,哈哈)
        User facebook =  new Facebook(cnboJavaDev);
        User google = new Google(cnboJavaDev);
        Article article1 = getArticle("學(xué)習(xí)筆記之單例設(shè)計(jì)模式", "cnbo");
        //cnboJavaDev發(fā)布一篇新文章article1,同時(shí)facebook和google
        //都接收到了更新,然后他哥倆有滋有味的讀者cnbo的文章。
        cnboJavaDev.addArticle(article1);
        Article article2 = getArticle("學(xué)習(xí)筆記之策略設(shè)計(jì)模式", "cnbo");
        cnboJavaDev.addArticle(article2);
    }
    
    public static Article getArticle(String title, String author) {
        Article article = new Article();
        article.setTitle(title);
        article.setAuthor(author);
        
        return article;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,544評(píng)論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,644評(píng)論 18 399
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的閱讀 13,653評(píng)論 5 6
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,962評(píng)論 25 709
  • 概要: 1.如果有色彩理論更好(美術(shù)功底) 2.玩色彩的方法 內(nèi)容 學(xué)習(xí)配色的三個(gè)方法 1.顏料涂鴉 買一點(diǎn)顏料,...
    波羅蜜啊閱讀 1,428評(píng)論 0 0

友情鏈接更多精彩內(nèi)容