天天看點

設計模式之觀察者模式(釋出訂閱模式)

說明:本文參照《大話設計模式》中的案例做簡要解析

觀察者模式:

        又叫釋出-訂閱模式,定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在發生變化時,會通知所有觀察者對象,使他們能夠更新自己。

        我自己的了解,可以拿咱們都比較熟悉的上課來做比喻,在一個教室裡,老師就是通知者,所有正在上課的學生就是觀察者,老師說下課,所有的學生下課回家。老師說的“下課”,就是這裡的“主題”,也可以叫話題(Topic),學生接受到這個“主題”,采取相應的動作-(收拾東西回家)。

類圖及簡要說明:

設計模式之觀察者模式(釋出訂閱模式)

Subject類,可了解為主題或者抽象通知者,一般用抽象類或接口實作。它把所有的觀察者對象的引用儲存在一個集合裡,每個主題都可以有任何數量的觀察者。

package com.uu.designPattern.observer;

import java.util.ArrayList;
import java.util.List;

/**
  ***********************************************
  * 主題或抽象通知者
  * 	一般用一個抽象類或一個接口實作,把所有對觀察者的引用儲存在一個集合裡,每一個主題都可以有任何數量的觀察者。
  * 	抽象主題提供一個接口,可以增加和删除觀察者。
  * @author UU
  * @date 2018年7月5日 下午3:00:23
  * @version 1.0
  ***********************************************
 */
public abstract class Subject {

	List<Observer> observers = new ArrayList<>();
	
	/**添加觀察者*/
	public abstract void attach(Observer observer); 
	/**移除觀察者*/
	public abstract void detach(Observer observer);
	
	/**
	 * 通知觀察者
	 */
	public void notifyAllObserver() {
		observers.forEach(Observer::update);
	}
	
}
           

Observer,抽象觀察者,為所有的具體觀察者定義一個接口,在得到主題的通知時,更新自己。這個接口稱為更新接口,更新接口一般都有一個update方法。

package com.uu.designPattern.observer;

/**
  ***********************************************
  * 觀察者
  * @author UU
  * @date 2018年7月5日 下午3:02:34
  * @version 1.0
  ***********************************************
 */
public abstract class Observer {

	public abstract void update();
}
           

ConcreteSubject,具體的主題或具體的通知者,将有關狀态存入具體觀察者對象;在具體主題的内部狀态發生改變時,給所有已經注冊的觀察者發出通知。其實這裡的意思主要是觸發通知者發出通知,然後觀察者根據通知資訊作出相應的動作。

package com.uu.designPattern.observer;

/**
 ***********************************************
 * 具體的主題或通知者,将有關狀态存入具體主題對象,在具體的主題對象的内部狀态發生改變時,通知所有已經注冊的觀察者
 * @author UU
 * @date 2018年7月5日 下午3:42:40
 * @version 1.0
 ***********************************************
 */
public class ConcreteSubject extends Subject{

	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	@Override
	public void attach(Observer observer) {
		this.observers.add(observer);
	}

	@Override
	public void detach(Observer observer) {
		this.observers.remove(observer);
	}

}
           

ConcreteObserver,具體的觀察者,實作抽象觀察者所要實作的更新方法,以便使自身的狀态與主題的狀态保持一緻。具體觀察者包含一個具體主題對象的引用。

package com.uu.designPattern.observer;

/**
 ***********************************************
 * 具體的觀察者
 * 
 * @author UU
 * @date 2018年7月5日 下午3:46:47
 * @version 1.0
 ***********************************************
 */
public class ConcreteObserver extends Observer {

	private String name;
	private String state;
	private ConcreteSubject subject;

	public ConcreteObserver(String name, ConcreteSubject subject) {
		super();
		this.name = name;
		this.subject = subject;
	}

	@Override
	public void update() {
		state = subject.getState();
		System.out.println("觀察者" + this.name + "的新狀态是:" + state);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public ConcreteSubject getSubject() {
		return subject;
	}

	public void setSubject(ConcreteSubject subject) {
		this.subject = subject;
	}

}
           

測試類:

package com.uu.designPattern.observer;

public class ObserverTest {

	public static void main(String[] args) {
		
		ConcreteSubject subject = new ConcreteSubject();
		subject.attach(new ConcreteObserver("AA", subject));
		subject.attach(new ConcreteObserver("BB", subject));
		
		subject.setState("ABC");
		subject.notifyAllObserver();
		
		subject.setState("CCC");
		subject.notifyAllObserver();
		
	}
}
           

運作結果:

觀察者AA的新狀态是:ABC
觀察者BB的新狀态是:ABC
觀察者AA的新狀态是:CCC
觀察者BB的新狀态是:CCC
           

觀察者模式的特點:

        主要是為了解決各類直接的耦合度,一個出題可以有任意數量的觀察者,一旦主題發生改變,所有注冊的觀察者都可以得到通知。主題發出通知時,并不需要知道他的觀察者都是哪些,也就是說,具體的觀察者是誰,他根本不需要知道,而任何一個觀察者不知道也不需要知道其他觀察者的存在。

        再拿老師和學生來講,老師不需要知道每個學生都是誰(也許是剛來的新老師),老師隻需要發出下課的指令就可以了,然後這個指令會被所有正在上課的學生接受到。對于每個學生個體而言,也不需要知道是否有其他學生是否存在,隻要接受到老師的指令,照做就OK了。

觀察者模式的應用場景:

        當一個對象的改變需要同時改變其他對象時,并且它不知道具體有多少對象需要改變。

總的來講,觀察者模式所做的工作就是解除耦合,讓耦合的雙方都依賴于抽象,而不是依賴于具體。進而使得各自的變化都不會影響到另一邊的變化。

在Dubbo的注冊中心Zookeeper中的服務注冊和訂閱應用的就是這種模式。

以上全是個人見解,若有錯誤,還望指正。

繼續閱讀