觀察者設計模式(observer)

Observer(觀察者)模式是比較常用的一個模式,他讓主題和觀察者之間松耦合

定義:定義對象間一對多的依賴,這樣一來,當一個對象發生改變,其他依賴者會得到通知並自動更新.

作爲觀察者,主題只知道他實現一個接口 Oberver,主題不需要知道他具體是誰,需要實現什麼操作.

任何時候我們都可以增加新的觀察者.因爲主題實現的是一個實現oberver的抽象接口列表,所以我們可以隨時增加和刪除觀察者

主題不用瞭解其他的,只需要給現有註冊的觀察者發消息就可以了,觀察者的增加和改變,不需要修改主題的代碼.

主題和觀察者,我們可以重複使用,改變一方不會影響另外一方,說到底就是爲了達到解耦合的目的.

應用場合:

新京報,他是一個主題,很多人都可以定購他,他不需要了解你訂購他是幹嗎,他只知道你付了錢,他給你一份報紙,到什麼地址.如果他修改版面,他會通知你,比如說,最近物價上漲.可能需要上漲幾毛錢.(有更改就會通知依賴者)

而訂購他的人或者公司,屬於觀察者也就是依賴者,只有2個參數,一個是註冊,一個是解除註冊.註冊後,就會收到報紙的最新消息,一有修改就會通知你.解除註冊後,你還是你,但是你已經不屬於依賴者了,就不會接到相應的消息.你可以今天註冊,今天解除(這是你的事情).不會影響到其他的東西,也就是松耦合.


首先我們來模擬JDK裏面有自帶的類實現觀察者模式:

實現一個電腦廠商和地區代理的示例,一對多關係依賴

GeneralProxy.java

package com.linpyi.computer;

/** 
 * 電腦總代理接口 
 * @author work 
 * 
 */  
public interface GeneralProxy {  
    /** 
     * 註冊電腦代理 
     * @param o 
     */  
    public void registerComputerProxy(Observer o);  
    /** 
     * 移除電腦代理 
     * @param o 
     */  
    public void removeComputerProxy(Observer o);  
    /** 
     * 更新代理價格 
     */  
    public void notifyComputerProxy();  
}  

Observer.java

package com.linpyi.computer;  
  
/** 
 * 電腦觀察者,自己寫的代理接口 
 * @author work 
 * 
 */  
public interface Observer {  
    /** 
     * 更新電腦信息 
     * @param name 電腦品牌 
     * @param price 電腦價格 
     * @param info 電腦描述 
     */  
    public void update(String name,float price,String info);  
}

BranchProxy.java

package com.linpyi.computer;  
/** 
 * 電腦分代理接口 
 * @author work 
 * 
 */  
public interface BranchProxy {  
    /** 
     * 默認方法 
     */  
    public void display();  
}  
LenvoComputer.java

package com.linpyi.computer;  
  
import java.util.ArrayList;  
  
/** 
 * lenovo電腦
 * @author work 
 * 
 */  
public class LenvoComputer implements GeneralProxy {  
      
    private ArrayList proxys ;  
    private String name;  
    private float price;  
    private String info;  
      
    public LenvoComputer(){  
        proxys = new ArrayList();  
    }
      
    /** 
     * 更改lenvo分代理的信息 
     */  
    public void notifyComputerProxy() {  
        for(int i = 0 ;i<proxys.size();i++){  
            Observer proxy = (Observer)proxys.get(i);  
            proxy.update(name, price, info);
        }
    }
      
    /** 
     * 設置lenvo的電腦價格和信息 
     * @param name 電腦名稱 
     * @param price 電腦價格 
     * @param info 電腦描述信息 
     */  
    public void setLenvo(String name,float price,String info){  
        this.name=name;  
        this.price=price;  
        this.info=info;  
        notifyComputerProxy();  
    }
  
    /** 
     * 註冊lenvo代理 
     */  
    public void registerComputerProxy(Observer o) {  
        proxys.add(o);  
    }  
  
    /** 
     * 移除lenvo代理 
     */  
    public void removeComputerProxy(Observer o) {  
        // TODO Auto-generated method stub  
        int i = proxys.indexOf(o);  
        if(i>=0){  
            proxys.remove(o);  
        }  
    }
}  

ChinaProxy.java

package com.linpyi.computer;  
  
/** 
 * 中國地區代理類,使用自己寫的代理接口 
 * @author  
 * 
 */  
public class ChinaProxy implements BranchProxy, Observer {  
      
    private GeneralProxy generalProxy;  
    private String name ;  
    private float price;  
    private String info;  
      
    public ChinaProxy(GeneralProxy generalProxy){  
        this.generalProxy=generalProxy;  
        generalProxy.registerComputerProxy(this);//註冊代理  
    }  
  
    /** 
     * 默認方法 
     */  
    public void display() {  
        // TODO Auto-generated method stub  
        System.out.println("中國代理");  
        System.out.println("型號"+name);  
        System.out.println("價格"+price);  
        System.out.println("描述信息"+info);  
    }  
  
    /** 
     * 更新方法 
     */  
    public void update(String name, float price, String info) {  
        // TODO Auto-generated method stub  
        this.name=name;  
        this.price=price;  
        this.info=info;  
        display();  
    }  
  
}  

JapanProxy.java

package com.linpyi.computer;  
  
/** 
 * 日本代理,使用自己寫的代理接口 
 *  
 * @author work 
 *  
 */  
public class JapanProxy implements BranchProxy, Observer {  
  
    private String name;  
    private String info;  
    private float price;  
    private GeneralProxy generalProxy;
  
    public JapanProxy(GeneralProxy generalProxy) {  
        this.generalProxy = generalProxy;  
        generalProxy.registerComputerProxy(this);  
    }  
  
    public void update(String name, float price, String info) {  
        this.name = name;  
        this.price = price;  
        this.info = info;  
        display();  
    }
  
    public void display() {  
        // TODO Auto-generated method stub  
        System.out.println("日本代理");  
        System.out.println("型號" + name);  
        System.out.println("價格" + price);  
        System.out.println("描述信息" + info);  
    }
}  
Client.java

package com.linpyi.computer;

public class Client {

    public static void main(String[] args){  
        //使用自己寫的觀察模式方法  
        LenvoComputer lenvo = new LenvoComputer();  
        ChinaProxy chinaProxy  = new ChinaProxy(lenvo);  
        JapanProxy japanProxy  = new JapanProxy(lenvo);  
        lenvo.setLenvo("lenvo0001", 8000, "disk 160G , memory 2G");  

    }
}    
使用JDK裏面有自帶的類實現觀察者模式:

HpComputer.java

package com.linpyi.computer;  
  
import java.util.Observable;  
  
/** 
 * HP電腦代理,使用的是JDK自帶的觀察者模式類(Observable) 
 * @author work 
 * 
 */  
public class HpComputer extends Observable {  
  
    private String name;  
    private float price;  
    private String info;  
      
    public void measurementsChanged(){  
        setChanged();//觀察者類裏的方法,主要用於開關  
        notifyObservers();//繼承類裏的方法(通知觀察者)  
    }  
      
    public void setMeasurements(String name,float price,String info){  
        this.name=name;  
        this.price=price;  
        this.info=info;  
        measurementsChanged();  
    }  
      
    public String getName(){  
        return name;  
    }  
      
    public float getPrice(){  
        return price;  
    }  
      
    public String getInfo(){  
        return info;  
    }  
    

}  

IndiaProxy.java

package com.linpyi.computer;  
  
import java.util.Observable;  
import java.util.Observer;  
  
/** 
 * 印度電腦代理(使用JDK自帶的接口) 
 * @author work 
 * 
 */  
public class IndiaProxy implements Observer, BranchProxy {  
      
    private Observable observable;  
    private String name;  
    private String info;  
    private float price;  
      
    public IndiaProxy(Observable observable) {  
        this.observable = observable;  
        observable.addObserver(this);//增加觀察者(JDK自帶的)  
    }  
  
    /** 
     * 更新方法,使用的是JDK自帶的方法 
     */  
    public void update(Observable o, Object arg) {  
        // TODO Auto-generated method stub  
        if (o instanceof HpComputer) {  
            HpComputer computer = (HpComputer) o;  
            this.name = computer.getName();  
            this.price = computer.getPrice();  
            this.info = computer.getInfo();  
            display();  
        }  
    }  
  
    public void display() {  
        // TODO Auto-generated method stub  
        System.out.println("印度代理");  
        System.out.println("型號" + name);  
        System.out.println("價格" + price);  
        System.out.println("描述信息" + info);  
    }  
  
}  

KoreaProxy.java

package com.linpyi.computer;  
  
import java.util.Observable;  
import java.util.Observer;  
  
/** 
 * 韓國代理,使用的是JDK自帶的接口(Observer) 
 * @author work 
 * 
 */  
public class KoreaProxy implements Observer, BranchProxy {  
    private Observable observable;  
    private String name;  
    private String info;  
    private float price;  
  
    public KoreaProxy(Observable observable) {  
        this.observable = observable;  
        observable.addObserver(this);  
    }
  
    public void update(Observable o, Object arg) {  
        // TODO Auto-generated method stub  
        if (o instanceof HpComputer) {  
            HpComputer computer = (HpComputer) o;  
            this.name = computer.getName();  
            this.price = computer.getPrice();  
            this.info = computer.getInfo();  
            display();  
        }  
    }  
  
    public void display() {  
        // TODO Auto-generated method stub  
        System.out.println("韓國代理");  
        System.out.println("型號" + name);  
        System.out.println("價格" + price);  
        System.out.println("描述信息" + info);  
    }  
  
}  

Client.java

package com.linpyi.computer;

public class Client {

    public static void main(String[] args){  
    	//使用JDK的觀察模式方法  
    	HpComputer hp = new HpComputer();  
    	KoreaProxy koreaProxy = new KoreaProxy(hp);  
    	IndiaProxy IndiaProxy = new IndiaProxy(hp);  
    	hp.setMeasurements("hp0001", 7000, "disk 250G , memory 10G");  

    }
}       

JDK裏面有自帶的類實現觀察者模式,在java.util.Observable,注意這是類而不是接口,類有類的侷限性,因爲JAVA只能繼承


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