1. 程式人生 > >深入淺出設計模式之策略模式、觀察者模式

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

第一章 入門

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()。