Observer 觀察者模式

在開發過程當中,咱們常常會碰到這樣的需求:若是一個對象A的狀態發生改變,某些與它相關的對象也要隨之作出相應的變化。一般來講,須要對象 A 能訪問到這些對象,從而去調用更新方法,可是這是一種不受歡迎的會形成耦合的方式。爲了低耦合,能夠採用觀察者模式。設計模式

定義

Observer 觀察者模式,屬於行爲型模式的一種,它定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在更改其狀態時,會通知全部的觀察者對象,使他們可以自動更新本身。一個主題對象能夠對應多個觀察者,而這些觀察者以前沒有相互聯繫,能夠根據須要增長和刪除觀察者,使得系統更易於拓展。bash

結構

  • Subject:抽象主題。抽象主題角色把全部觀察者對象保存在一個集合裏,每一個主題均可以有任意數量的觀察者,抽象主題提供一個接口,能夠增長和刪除觀察者對象。
  • ConcreteSubject:具體主題。該角色將有關狀態存入具體觀察者對象,在具體主題的內部狀態發生改變時,給全部訂閱過的觀察者發送通知。
  • Observer:抽象觀察者,是觀察者者的抽象類,它定義了一個更新接口,使得在獲得主題更改通知時更新本身。
  • ConcrereObserver:具體觀察者,實現抽象觀察者定義的更新接口,以便在獲得主題更改通知時更新自身的狀態。

簡單實現

  • 抽象主題類
abstract class Subject {
        private Vector obs = new Vector();


        public void addObserver(Observer obs){
            this.obs.add(obs);
        }
        public void delObserver(Observer obs){
            this.obs.remove(obs);
        }
        protected void notifyObserver(){
            for(Observer o: obs){
                o.update();
            }
        }
        public abstract void doSomething();
    }複製代碼
  • 具體主題類
class ConcreteSubject extends Subject {
        public void doSomething(){
            System.out.println("被觀察者事件反生");
            this.notifyObserver();
        }
    }複製代碼
  • 抽象觀察者
interface Observer {
        public void update();
    }複製代碼
  • 具體觀察者
class ConcreteObserver1 implements Observer {
        public void update() {
            System.out.println("觀察者1收到信息,並進行處理。");
        }
    }
    class ConcreteObserver2 implements Observer {
        public void update() {
            System.out.println("觀察者2收到信息,並進行處理。");
        }
    }複製代碼
  • 使用
public class Client {
        public static void main(String[] args){
            Subject sub = new ConcreteSubject();
            sub.addObserver(new ConcreteObserver1()); //添加觀察者1
            sub.addObserver(new ConcreteObserver2()); //添加觀察者2
            sub.doSomething();
        }
    }複製代碼

運行結果:post

被觀察者事件反生
觀察者1收到信息,並進行處理。
觀察者2收到信息,並進行處理。

實例

NSNotificationCenter 和 NSNotificationui

iOS 中的通知機制是很是典型的觀察者模式,全部的類能夠經過 NSNotificationCenter 監聽和發送 NSNotification,觀察者和被觀察者都無需知曉對方,只須要經過標記(例如 NotificationName)在 NSNotificationCenter 中找到監聽該通知所對應的類,從而調用該類的方法。而且,在 NSNotificationCenter 中,觀察者能夠只訂閱某一特定的通知,並對其作出響應,而不用對某一個類發送的全部通知都進行更新操做。NSNotificationCenter 對觀察者的調用不是隨機的,而是遵循註冊順序一一執行,而且在該線程內是同步的。this

@property (class, readonly, strong) NSNotificationCenter *defaultCenter;


- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;


- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;


- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObjec複製代碼

優缺點

優勢

1. 解除耦合,讓耦合的雙方都依賴於抽象,從而使得各自的變換都不會影響另外一邊的變換。spa

2. 觀察者模式符合「開閉原則」的要求,若須要引入新的觀察者,無需對被觀察對象進行修改線程

缺點

1. 若是一個觀察目標對象有不少直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間,同時,開發和調試的複雜程度提升設計

2. 若是在觀察者和觀察目標之間有循環依賴,有可能會進行循環調用,致使系統崩潰3d

和其餘設計模式的對比

責任鏈模式

觀察者模式也能夠將通知鏈式分就會發,與責任鏈模式十分類似調試

1. 責任鏈模式中,每一個接收者都包含對另外一個接收者的引用,而觀察者模式中,被觀察者並不知曉觀察者具體是誰

2. 在純責任鏈模式中,只有一個接收者會對請求進行處理,觀察者模式容許每一個觀察者都進行處理

命令模式

1. 命令模式是一對一的關係,觀察者模式是一對多的關係

2. 命令模式是經過發送命令讓接收方來執行,而觀察者模式中發出消息的類(被觀察者)並不關心接收消息的類(觀察者)會如何處理

中介者模式

中介者模式各個組件之間經過中介創建的是雙向鏈接,而觀察者模式的被觀察者和觀察者之間是單向的。

中模式與觀察者模式難以被區分的緣由之一是中介者模式的一個流行實現依賴於觀察者模式。中介對象扮演發佈者的角色,組件充當觀察者,訂閱和取消訂閱中介的事件。當以這種方式實現中介者模式時,它可能看起來很是相似於觀察者模式。可是,中介者模式還能夠用其餘方式實現。例如,能夠將全部組件永久連接到同一個中介對象。這個實現不像觀察者模式,但仍然是中介者模式。

相關文章
相關標籤/搜索