在一對多依賴的對象關係中, 若是這個'一'對象狀態發生了變化,那麼它全部依賴的'多'對象都應該被通知,而後作相應的變化,這就是觀察者模式. 就如同'多'對象一直在觀察'一'對象的狀態變化同樣.java
在觀察者模式中最重要的倆個對象分別是:Observable和Observer對象.它們的關係可總結以下:api
1. Observable和Observer對象是一對多的關係,也就是說一旦Observable對象狀態變化,它就要負責通知全部和它有關係的Observer對象,而後作相應的改變.測試
2. Observable對象不會主動去通知各個具體的Observer對象其狀態發生了變化,而是提供一個註冊接口供Observer對象使用,任何一個Observer對象若是想要被通知,則能夠使用這個接口來註冊.this
3. 在Observable中有一個集合和一個狀態控制開關,全部註冊了通知的Observer對象會被保存在這個集合中.這個控制開關就是用來控制Observable是否發生了變化,一旦發生了變化,就通知全部的Observer對象更新狀態.spa
在java api中分別提供了Observable對象:java.util.Observable和Observer接口:java.util.Observer. 下面用實例來實現一下觀察者模式: 股票系統orm
全部的類以下:server
StockData (Observable對象,也就是所股票數據發生了變化,它就要通知全部和它有關係的交易實體作相應的變化)對象
BigBuyer (Observer對象, 實現了Observer接口)接口
TradingFool (Observer對象, 實現了Observer接口)ci
StockQuote 測試類
在這個例子中一旦StockData對象的狀態發生了變化,那BigBuyer和TradingFool都應該受到通知:
StockData.java:
Java代碼
import java.util.Observable;
public class StockData extends Observable
{
private String symbol;
private float close;
private float high;
private float low;
private long volume;
public StockData()
{}
public String getSymbol()
{
return symbol;
}
public float getClose()
{
return close;
}
public float getHigh()
{
return high;
}
public float getLow()
{
return low;
}
public long getVolume()
{
return volume;
}
public void sendStockData()
{
setChanged();
notifyObservers();
}
public void setStockData(String symbol,float close,float high,float low,long volume)
{
this.symbol = symbol;
this.close = close;
this.high = high;
this.low = low;
this.volume = volume;
sendStockData();
}
}
BigBuyer.java:
Java代碼
public class BigBuyer implements Observer
{
private String symbol;
private float close;
private float high;
private float low;
private long volume;
public BigBuyer(Observable observable)
{
observable.addObserver(this); //註冊關係
}
public void update(Observable observable,Object args)
{
if(observable instanceof StockData)
{
StockData stockData = (StockData)observable;
this.symbol = stockData.getSymbol();
this.close = stockData.getClose();
this.high = stockData.getHigh();
this.low = stockData.getLow();
this.volume = stockData.getVolume();
display();
}
}
public void display()
{
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
DecimalFormat volumeFormat = new DecimalFormat("###,###,###,###",dfs);
DecimalFormat priceFormat = new DecimalFormat("###.00",dfs);
System.out.println("Big Buyer reports... ");
System.out.println("\tThe lastest stock quote for " + symbol + " is:");
System.out.println("\t$" + priceFormat.format(close) + " per share (close).");
System.out.println("\t$" + priceFormat.format(high) + " per share (high).");
System.out.println("\t$" + priceFormat.format(low) + " per share (low).");
System.out.println("\t" + volumeFormat.format(volume) + " shares traded.");
System.out.println();
}
}
TradingFool.java:
Java代碼
public class TradingFool implements Observer
{
private String symbol;
private float close;
public TradingFool(Observable observable)
{
observable.addObserver(this);//註冊關係
}
public void update(Observable observable,Object args)
{
if(observable instanceof StockData)
{
StockData stockData = (StockData)observable;
this.symbol = stockData.getSymbol();
this.close = stockData.getClose();
display();
}
}
public void display()
{
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
DecimalFormat priceFormat = new DecimalFormat("###.00",dfs);
System.out.println("Trading Fool says... ");
System.out.println("\t" + symbol + " is currently trading at $" + priceFormat.format(close) + " per share.");
System.out.println();
}
}
StokeQuote.java
Java代碼
public class StockQuotes
{
public static void main(String[] args)
{
System.out.println();
System.out.println("-- Stock Quote Application --");
System.out.println();
StockData stockData = new StockData();
// register observers...
new TradingFool(stockData);
new BigBuyer(stockData);
// generate changes to stock data...
stockData.setStockData("JUPM",16.10f,16.15f,15.34f,(long)481172);
stockData.setStockData("SUNW",4.84f,4.90f,4.79f,(long)68870233);
stockData.setStockData("MSFT",23.17f,23.37f,23.05f,(long)75091400);
}
}
在測試類中咱們能夠看到倆個Observer對象都註冊了Observable對象,而當Observable對象發生改變時,這倆個Observable對象就會作相應的更新了, 運行結果以下:
Java代碼
Big Buyer reports...
The lastest stock quote for JUPM is:
$16.10 per share (close).
$16.15 per share (high).
$15.34 per share (low).
481,172 shares traded.
Trading Fool says...
JUPM is currently trading at $16.10 per share.
Big Buyer reports...
The lastest stock quote for SUNW is:
$4.84 per share (close).
$4.90 per share (high).
$4.79 per share (low).
68,870,233 shares traded.
Trading Fool says...
SUNW is currently trading at $4.84 per share.
Big Buyer reports...
The lastest stock quote for MSFT is:
$23.17 per share (close).
$23.37 per share (high).
$23.05 per share (low).
75,091,400 shares traded.
Trading Fool says...
MSFT is currently trading at $23.17 per share.
咱們經過Observable源碼能夠看到,其實Observable對象不關心具體的Observer的實例類型. 只要是實現了Observer接口的Observer對象均可以獲得通知,這就爲咱們若是想要對模型進行擴展提供了方便,使Observable對象和 Observer對象實現了鬆耦合. 若是咱們須要添加一個新的Observer對象時,咱們只要註冊一下,當Observable對象發生變化時就能夠獲得通知,而不要作其餘任何改變,很是 方便.