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只能繼承