深入淺出設計模式之策略模式、觀察者模式

第一章 入門

1.這裏講了一個簡單的例子,鴨子的例子。鴨子都會叫,都會走,都會游泳(不變的部分)。但是有的鴨子會飛,有的鴨子的外觀不一樣等等(變得部分),如何設計呢?採取分離的策略,將不變的部分和可變的部分分離,因此引出我們第一個設計原則:找出應用中可能需要的變化之處,把它們獨立出來,不要和哪些不需要變化的代碼混在一起。

2.如何設計呢?對於上面的鴨子的例子,我們知道我們要增強我們的代碼彈性, 就是說要更容易修改,引出第二個設計原則:針對接口編程,而不是針對實現編程。具體來講,對於我們鴨子的每個可變行爲,比如飛行行爲,單獨拿出來作爲一個接口。如下圖


3.接下來,你就應該要整合鴨子的行爲了。前面的過程,我們將鴨子的可變行爲委託(delegate)給了FlayBehavior和QuackBehavior。具體的做法是讓鴨子類持有FlyBehavior和QuackBehavior的兩個實例變量,然後寫兩個方法,比如飛行方法,如下所示

public void performFly(){ flyBehavior.fly();}

這樣鴨子就有了自己的飛行行爲,我們只需要在實例化這個鴨子的時候,比如在構造函數中初始化對應的飛行和名叫的具體的類即可。


4.第三個設計原則:多用組合,少用繼承。

上述就講述了一個設計模式策略模式,而且是一個多策略模式,有飛行的策略,有名叫的策略,不同的策略下面又有不同的實現。

觀察者模式

觀察者模式適用於經常變化且需要被監測的對象。課本上舉的例子是氣象站的一個類WebData,這個Webdata能獲得最新的氣象數據並及時的更新到三個佈告板。佈告板也不能僅僅只有3個,知識說現在有三個, 以後可能會有更多的佈告板展示其他的數據(可拓展性)。
怎麼辦呢?
基本的過程呢,我們用一個簡單的例子來解釋:假設觀察者是訂閱報紙的人,簡稱狗,鴨子,貓和老鼠,他們都訂閱了某個報社的報紙(假設鴨子還沒訂閱)。而被訂閱的報社呢,是被觀察者,就叫他們報社。整體的工作流程如下:
某天,鴨子向報社說,我想訂閱一份報紙(鴨子相當觀察者了),這個過程稱作註冊;
報社街道訂閱通知,將鴨子添加到自己的訂閱列表;
好,現在鴨子也加入到了觀察者裏面,開始等待報社送報紙(發送通知);
報社印出了新的報紙,並告訴觀察者們報紙已經好了;

老鼠不想當觀察者了,想訂閱另一個報社的報紙,於是老鼠向報社發送請求,然後老鼠離開了,刪除了一個觀察者。
報社又產生了新的報紙,只不過老鼠已經接收不到通知了。

那麼我們基本就瞭解了觀察者模式的工作流程了,那麼觀察者模式應該具體怎麼實現呢?我們來看類圖

一定要注意這幾個方法,對於被觀察者(主題,Subject),registerObserver,RemoveObserver,NotifyObserver,對於觀察者,只需要一個update。這是一個鬆耦合的設計,觀察者只需要等待主題的通知,而主題只知道觀察者只有一個update 方法。剩下的就比較簡單了。你可以寫一個Client類,這個類通過持有觀察者和被觀察者兩個接口,不斷的向被觀察者內部註冊觀察者或者移除觀察者。或者當被觀察者需要通知觀察者時,由Client調用notifyObservers()方法。

java內部實現了觀察者模式,Observervable抽象類負責被觀察者,Observer接口負責觀察者,如下圖所示



java內置的觀察者模式必須要經過兩步。即當被觀察者更新內容後,必須先setChange(),然後才能調用notifyObserver()看下面的代碼
觀察者
import java.util.Observable;
import java.util.Observer;

public class BlackBoard implements Observer{

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		if(o instanceof Teacher){
			Teacher teacher = (Teacher)o;
			System.out.println(teacher.getContent());
		}
		
	}

}
被觀察者
import java.util.Observable;

public class Teacher extends Observable{
	private String content;
	public Teacher(){
	
	}
	
	public void measurementsChanged(){
		setChanged();
		notifyObservers();
	}

	public void setContent(String content){
		this.content=content;
		measurementsChanged();
		
	}
	public String getContent() {
		// TODO Auto-generated method stub
		return content;
	}

}
客戶端:
public class Client {
	
	public static void main(String[] args){
		Teacher t = new Teacher();
		t.addObserver(new BlackBoard());
		t.setContent("Course Content");
//		t.measurementsChanged();
		t.setContent("new Content");
	}

}

總結一下,觀察者模式需要以下步驟:
1、創建觀察者和被觀察者,這裏觀察者需要有update()方法,被觀察者需要有addObserver(),removeObserver(),notifyOverver()方法。甚至還有自己的狀態setChange()表示當前數據有沒有更新。
2、在被觀察者內部註冊觀察者,這個可以在客戶端或者觀察者內部甚至被觀察者內部執行,都無所謂的。
3、被觀察者更新內容,設置setChange(),通知所有客戶端notifyObservers()。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章