我將初次學習設計模式的一些思維活動記錄如下,如有謬論請不吝斧正。
觀察者模式
定義對象之間的一對多的依賴關係,當一個對象改變狀態,它的依賴者都會收到通知並自動更新
出版社是主題對象,讀者們是依賴者對象。一旦出版者改變狀態有了新刊,訂閱者們就會 收到通知並更新自己的狀態。
這就產生了依賴關係。突然一天訂閱者A要退刊,他就不再是出版社的依賴者,自然不會再接受出版社的通知。
實現:包含Subject和Observer接口的類設計
建立接口(面向接口編程)
public interface Subject{
public void reqisterObserver(Observer o); //註冊觀察者對象
public void removeObserver(Observer o); //刪除觀察者對象
public void notifyObservers(); //主題狀態改變時通知觀察類
}
public interface Observer{
public void update(狀態作爲參數); //當狀態改變時,主題把這些狀態當作參數傳進來通知觀察者
}
public interface Things{ //封裝觀察者變化的行爲,面向接口編程
public void doThing();
}
建立主題類並實現主題接口
public class Publisher implements Subject{
private ArrayLiat observers; //記錄觀察者
private String name1;
private String name2;
public Publisher{
observers=new ArrayList(); //構造時建立
}
//實現主題接口
public void reqisterObserver(Observer o){
observers.add(o); //面向接口編程
}
public void removeObserver(Observer o){
int i=obsrvers.indexOf(o);
if(i>0)
observers.remove(i);
}
public void notifyObservers(){
for(int i=0;i<observers.size();i++){
Observers observer=(Observer)observers.get(i); //獲取觀察者對象
observer.update(name1,name2); //狀態做參數
}
}
//當狀態是否改變,是的話調用notifyObverservers();
public void nameChanged(){
if(...)
notifyObservers();
}
//獲取狀態,並
public void setMeasurements(String name1,String name2){
this.name1=name1;
this.name1=name2;
nameChanged();
}
}
建立觀察者類
public class reader implements Observer,Things{
private String name1;
private Subject p;
//每次初始化對象在主題對象中註冊
public reader(Subject p){
this.p=p;
p.refisterObverser(this); //面向接口編程
}
//當update在主題中被調用時,把需要的狀態保存下來,並執行相關處理
public void update(String name1,String name2){
this.name1=name1;
doThing();
}
//這個觀察者類的行爲
public void doThing(){}
}
**總結**
變化的是主題的狀態、觀察者的數目類型,利用兩接口封裝了這些變化。
面向接口編程,觀察者利用主題接口註冊,運行時觀察者組合進主題產生了依賴關係。
主題不知道觀察者具體類是誰等其他細節,只知道觀察者實現了Observer接口,
利用接口通知觀察者,可以改變觀察者卻不用改變主題,具有松耦合優點。
松耦合:兩對象之間松耦合,可互相交互,不太清楚彼此的細節
第三個設計原則:爲了交互對象之間的松耦合設計而努力
松耦合的設計可以建立有彈性的OO系統,因爲對象間的互相依賴降到了最低所以能應對變化。
以上,主題主動推送狀態。還可以由觀察者通過主題主動獲取,這樣不用修改更新對每位觀察者的調用,只需要增加get方法。
Java內置的Onserver模式支持以上兩種做法(util)
主題(可觀察者)繼承Observable類,觀察者實現Observer接口調用繼承下來的addObserver()
推送狀態:setChanged() 改變標誌,決定是否發送通知(擴展性);notifyservers(Object arg);
接收狀態:update(Observable o,Object arg);
利用java內置實現觀察者主動獲取狀態
觀察者調用所需get方法,setChanged判斷後決定是否發送
public class Publisher extends observable{
private String name1;
private String name2;
public Publisher{
}
public void namesChanged(){
setChanged();
notifyObservered();
}
//設置name並判斷是否要傳送狀態
public void setMeadurements(String name1,String name2){
this.name1=name1;
this.name2=name2;
namesChanged();
}
//get方法
public String getName1(){
return name1;
}
public String getName2(){
return name2;
}
}
public class reader implements Observer,Things{
Observable observable;
private String name1;
//構造時將reader註冊成觀察者
public reader(Observable observable){
this.observable=observable;
observable.addObserver(this);
}
//update方法增加Observable和數據對象作爲參數
public update(Observable obs,Object arg){
if(obs instanceof Publisher){
Publisher publisher=(Publisher)obs;
this.name1=publisher.getName1();
doThing();
}
}
//reader觀察者對狀態的炒作
public void doThing(){}
}
Observable類的一些問題:
- 必須要繼承它,但java又不支持多繼承;
- 不是接口,無法自己建立實現;
- setChanged方法被保護,除非繼承否則無法實例組合。
觀察者模式在JDK中有很多應用,以松耦合方式在一系列對象之間溝通狀態。