Java 設計模式之觀察者模式

今天學習了一下觀察者模式,做一下總結。

什麼是觀察者模式?

  觀察者模式:定義對象間的一種一對多依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知並被自動更新。

 觀察者模式也叫“依賴”或者“發佈——訂閱”模式。舉一些例子來說明什麼是觀察者模式。

   比如訂閱者報刊之間就屬於目標(subject)與觀察者(observer)關係。每一個訂閱者相當於一個觀察者,而這些觀察者是依賴於出版社的,當出版社的狀態發生改變時即就是有新的期刊時,所有依賴於它的訂閱者將得到通知,並會收到最新的報刊。

   再比如我們程序中例子,數據與界面之間的關係。一個表格對象和一個柱狀圖對象可以使用不同的表現形式描述同一一個應用的數據對象的信息。當數據對象的信息改變時,這些界面裏的數據也將會得到改變。而表格對象與柱狀圖對象是沒有依賴關係的。

觀察者模式的參與者

  • Subject(目標)
    目標知道它的觀察者,但是不知道具體是誰。可以有任意多個觀察者觀察同一個目標。
    提供註冊和刪除觀察對象的接口
  • Observer(觀察者)
    爲那些在目標發生改變時需要獲得通知的對象定義一個更新接口。
  • ConcreteSubject(具體目標)
    將有關狀態存入各ConcretSubject對象
    當它的狀態發生改變時,向他的各個觀察者發出通知。
  • ConcreteObserver(具體觀察者)
    維護一個指向ConcreteSubjec對象的引用。
    存儲有關狀態,將這些狀態與目標的狀態保持一致
    實現Observer的更新接口以使自身狀態與目標的狀態保持一致。

爲什麼要使用觀察者模式?

  將一個系統分割成一些列相互協作的類時有一個副作用:需要維護相關對象間的一致性。而這個時候,維護他們之間的一致性是非常不容易的,因爲他們之間緊密耦合,相互依賴,這樣重用性降低。而觀察者模式是鬆耦合的,因此重用性會得到提高。

什麼時候使用觀察者模式?

  • 當一個對象模型有兩個方面,其中一個方面依賴於另一個方面。將這二者封裝在獨立的對象中以使他們可以各自獨立的改變和複用。
  • 當對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象有待改變。
  • 當一個對象必須通知其他對象,而他又不能假定其他對象是誰。也就是說,我們不希望這些對象是緊密耦合。

 如何使用觀察者模式

 下面通過一個示例來說明。

 

/*
 * 出版社的抽象接口
 */
public interface Subject {
    //移除觀察者
    public void removeObserver(Observer o);
    //添加觀察者
    public void addObserver(Observer o);
    //通知觀察者
    public void notifyObservers();
}

/*
 * 具體的目標對象 這裏假定爲“讀者出版社”
 */
public class ConcreteSubject implements Subject{
	private ArrayList<Observer> observers;
	private String book;
	public ConcreteSubject() {
		observers = new ArrayList<Observer>();
	}
	@Override
	public void removeObserver(Observer o) {
		int i= observers.indexOf(o);
		if(i>=0) {
			observers.remove(i);
		}
	}

	@Override
	public void addObserver(Observer o) {
		observers.add(o);
	}

	@Override
	public void notifyObservers() {
		for(int i=0;i<observers.size();i++) {
			observers.get(i).update(book);
		}
	}
	//設置狀態信息的改變方法 當有新書時 可通過此方法進行添加
	public void setState(String book) {
		this.book = book;
	}
	//通過此方法 訂閱者(observer)可以主動得到目標(subject)中的書
	public String getState() {
		return book;
	}
}

/*
 * 觀察者的抽象接口,擁有一個update()方法 當目標(subject)狀態改變時 調用此方法
 */
public interface Observer {
	public void update(String book);
}

/*
 * 訂閱者共有的接口 張三和李四訂閱者都必須實現這個接口 因爲他們有共同的方法display
 */
public interface DisplayElement {
	public void display();
}

/*
 * 訂閱者 李四
 */
public class Observer1 implements Observer,DisplayElement{
	private Subject subject;
	private String book;
	public Observer1(Subject subject) {
		this.subject = subject;
		subject.addObserver(this);
	}
	@Override
	public void update(String book) {
		this.book = book;
		display();
	}
	@Override
	public void display() {
		System.out.println("Observer1 收到了一本新書:"+book);
	}
}

/*
 * 訂閱者 張三
 */
public class Observer2 implements Observer,DisplayElement{
	private String book;
	private Subject subject;
	public Observer2(Subject subject) {
		this.subject = subject;
		subject.addObserver(this);
	}

	@Override
	public void update(String book) {
		this.book = book;
		display();
	}
	@Override
	public void display() {
		System.out.println("observer2 收到了一本新書:"+book);
	}

}

public class ObserverTest {
	public static void main(String[] args) {
		ConcreteSubject subject = new ConcreteSubject();
		Observer1 zhangsan = new Observer1(subject);
		Observer2 lisi = new Observer2(subject);
		subject.setState("讀者第一刊");
		subject.notifyObservers();
	}

}




發佈了46 篇原創文章 · 獲贊 63 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章