設計模式 - 觀察者模式(Observer Pattern) 詳解

觀察者模式(Observer Pattern) 詳解


本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157


版權所有, 禁止轉載, 如有轉載, 請站內聯繫.


觀察者模式(Observer Pattern): 定義了對象之間的一對多的依賴, 這樣一來, 當一個對象改變狀態時, 它的所有依賴者都會收到通知並自動更新.


使用方法:


1. 首先新建主題(subject)接口, 負責註冊(register)\刪除(remove)\通知(notify)觀察者; 觀察者(observer)接口,  負責更新(update)數據;

主題(subject)接口: 註冊觀察者(registerObserver), 刪除觀察者(removeObserver), 通知觀察者(notifyObservers, 通知所有觀察者);

觀察者(observer)接口: 更新(update);


代碼:

  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public interface Subject {  
  11.     public void registerObserver(Observer o);  
  12.     public void removeObserver(Observer o);  
  13.     public void notifyObervers();  
  14. }  
  15.   
  16.   
  17. /** 
  18.  * @time 2014年5月22日 
  19.  */  
  20. package observer;  
  21.   
  22. /** 
  23.  * @author C.L.Wang 
  24.  * 
  25.  */  
  26. public interface Observer {  
  27.     public void update(float temp, float humidity, float pressure);  
  28. }  
  29.   
  30.   
  31. /** 
  32.  * @time 2014年5月22日 
  33.  */  
  34. package observer;  
  35.   
  36. /** 
  37.  * @author C.L.Wang 
  38.  * 
  39.  */  
  40. public interface DisplayElement {  
  41.     public void display();  
  42. }  
/**
 * @time 2014年5月22日
 */
package observer;

/**
 * @author C.L.Wang
 *
 */
public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObervers();
}


/**
 * @time 2014年5月22日
 */
package observer;

/**
 * @author C.L.Wang
 *
 */
public interface Observer {
	public void update(float temp, float humidity, float pressure);
}


/**
 * @time 2014年5月22日
 */
package observer;

/**
 * @author C.L.Wang
 *
 */
public interface DisplayElement {
	public void display();
}

2. 實現主題(subject)接口, 通過列表(list)的形式註冊(register)和刪除(remove)觀察者, 

通知(notify)觀察者時, 循環調用所有已註冊的觀察者的更新(update)動作;

通過接口函數(set), 封裝通知(notify)動作, 傳入參數並進行通知.


代碼:

  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. import java.util.ArrayList;  
  7.   
  8. /** 
  9.  * @author C.L.Wang 
  10.  * 
  11.  */  
  12. public class WeatherData implements Subject {  
  13.       
  14.     public ArrayList<Observer> observers;  
  15.     private float temperature;  
  16.     private float humidity; //溼度  
  17.     private float pressure;  
  18.       
  19.     public WeatherData() {  
  20.         observers = new ArrayList<Observer>();  
  21.     }  
  22.       
  23.     /* (non-Javadoc) 
  24.      * @see observer.Subject#registerObserver(observer.Observer) 
  25.      */  
  26.     @Override  
  27.     public void registerObserver(Observer o) {  
  28.         // TODO Auto-generated method stub  
  29.         observers.add(o);  
  30.     }  
  31.   
  32.     /* (non-Javadoc) 
  33.      * @see observer.Subject#removeObserver(observer.Observer) 
  34.      */  
  35.     @Override  
  36.     public void removeObserver(Observer o) {  
  37.         // TODO Auto-generated method stub  
  38.         int i = observers.indexOf(o);  
  39.         if (i>=0) {  
  40.             observers.remove(i);  
  41.         }  
  42.     }  
  43.   
  44.     /* (non-Javadoc) 
  45.      * @see observer.Subject#notifyObervers() 
  46.      */  
  47.     @Override  
  48.     public void notifyObervers() {  
  49.         // TODO Auto-generated method stub  
  50.         for (int i=0; i<observers.size(); ++i) {  
  51.             Observer observer = (Observer)observers.get(i);  
  52.             observer.update(temperature, humidity, pressure);  
  53.         }  
  54.     }  
  55.       
  56.     public void measurementsChanged() {  
  57.         notifyObervers();  
  58.     }  
  59.       
  60.     public void setMeasurements(float temperature, float humidity, float pressure) {  
  61.         this.temperature = temperature;  
  62.         this.humidity = humidity;  
  63.         this.pressure = pressure;  
  64.         measurementsChanged();  
  65.     }  
  66.   
  67. }  
/**
 * @time 2014年5月22日
 */
package observer;

import java.util.ArrayList;

/**
 * @author C.L.Wang
 *
 */
public class WeatherData implements Subject {
	
	public ArrayList<Observer> observers;
	private float temperature;
	private float humidity; //溼度
	private float pressure;
	
	public WeatherData() {
		observers = new ArrayList<Observer>();
	}
	
	/* (non-Javadoc)
	 * @see observer.Subject#registerObserver(observer.Observer)
	 */
	@Override
	public void registerObserver(Observer o) {
		// TODO Auto-generated method stub
		observers.add(o);
	}

	/* (non-Javadoc)
	 * @see observer.Subject#removeObserver(observer.Observer)
	 */
	@Override
	public void removeObserver(Observer o) {
		// TODO Auto-generated method stub
		int i = observers.indexOf(o);
		if (i>=0) {
			observers.remove(i);
		}
	}

	/* (non-Javadoc)
	 * @see observer.Subject#notifyObervers()
	 */
	@Override
	public void notifyObervers() {
		// TODO Auto-generated method stub
		for (int i=0; i<observers.size(); ++i) {
			Observer observer = (Observer)observers.get(i);
			observer.update(temperature, humidity, pressure);
		}
	}
	
	public void measurementsChanged() {
		notifyObervers();
	}
	
	public void setMeasurements(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}

}

3. 實現觀察者(observer)接口, 主要保存收到的數據, 並實現更新(update)動作, 即把數據保存在本地;

構造函數中, 把自己註冊(register)入, 傳入的主題(subject)參數, 使主題可以通知觀察者.


代碼:

  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public class CurrentConditionsDisplay implements Observer, DisplayElement {  
  11.       
  12.     private float temperature;  
  13.     private float humidity;  
  14.     private Subject weatherData;  
  15.       
  16.     public CurrentConditionsDisplay(Subject weatherData) {  
  17.         this.weatherData = weatherData;  
  18.         weatherData.registerObserver(this);  
  19.     }  
  20.       
  21.     /* (non-Javadoc) 
  22.      * @see observer.DisplayElement#display() 
  23.      */  
  24.     @Override  
  25.     public void display() {  
  26.         // TODO Auto-generated method stub  
  27.         System.out.println("Current conditions: " + temperature +  
  28.                 "F degrees and " + humidity + "% humidity");  
  29.     }  
  30.   
  31.     /* (non-Javadoc) 
  32.      * @see observer.Observer#update(float, float, float) 
  33.      */  
  34.     @Override  
  35.     public void update(float temperature, float humidity, float pressure) {  
  36.         // TODO Auto-generated method stub  
  37.         this.temperature = temperature;  
  38.         this.humidity = humidity;  
  39.         display();  
  40.     }  
  41.   
  42. }  
  43.   
  44.   
  45. package observer;  
  46.   
  47. import java.util.*;  
  48.   
  49. public class ForecastDisplay implements Observer, DisplayElement {  
  50.     private float currentPressure = 29.92f;    
  51.     private float lastPressure;  
  52.     private WeatherData weatherData;  
  53.   
  54.     public ForecastDisplay(WeatherData weatherData) {  
  55.         this.weatherData = weatherData;  
  56.         weatherData.registerObserver(this);  
  57.     }  
  58.   
  59.     public void update(float temp, float humidity, float pressure) {  
  60.                 lastPressure = currentPressure;  
  61.         currentPressure = pressure;  
  62.   
  63.         display();  
  64.     }  
  65.   
  66.     public void display() {  
  67.         System.out.print("Forecast: ");  
  68.         if (currentPressure > lastPressure) {  
  69.             System.out.println("Improving weather on the way!");  
  70.         } else if (currentPressure == lastPressure) {  
  71.             System.out.println("More of the same");  
  72.         } else if (currentPressure < lastPressure) {  
  73.             System.out.println("Watch out for cooler, rainy weather");  
  74.         }  
  75.     }  
  76. }  
  77.   
  78.   
  79. package observer;  
  80.   
  81. import java.util.*;  
  82.   
  83. public class StatisticsDisplay implements Observer, DisplayElement {  
  84.     private float maxTemp = 0.0f;  
  85.     private float minTemp = 200;  
  86.     private float tempSum= 0.0f;  
  87.     private int numReadings;  
  88.     private WeatherData weatherData;  
  89.   
  90.     public StatisticsDisplay(WeatherData weatherData) {  
  91.         this.weatherData = weatherData;  
  92.         weatherData.registerObserver(this);  
  93.     }  
  94.   
  95.     public void update(float temp, float humidity, float pressure) {  
  96.         tempSum += temp;  
  97.         numReadings++;  
  98.   
  99.         if (temp > maxTemp) {  
  100.             maxTemp = temp;  
  101.         }  
  102.    
  103.         if (temp < minTemp) {  
  104.             minTemp = temp;  
  105.         }  
  106.   
  107.         display();  
  108.     }  
  109.   
  110.     public void display() {  
  111.         System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)  
  112.             + "/" + maxTemp + "/" + minTemp);  
  113.     }  
  114. }  
/**
 * @time 2014年5月22日
 */
package observer;

/**
 * @author C.L.Wang
 *
 */
public class CurrentConditionsDisplay implements Observer, DisplayElement {
	
	private float temperature;
	private float humidity;
	private Subject weatherData;
	
	public CurrentConditionsDisplay(Subject weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}
	
	/* (non-Javadoc)
	 * @see observer.DisplayElement#display()
	 */
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("Current conditions: " + temperature +
				"F degrees and " + humidity + "% humidity");
	}

	/* (non-Javadoc)
	 * @see observer.Observer#update(float, float, float)
	 */
	@Override
	public void update(float temperature, float humidity, float pressure) {
		// TODO Auto-generated method stub
		this.temperature = temperature;
		this.humidity = humidity;
		display();
	}

}


package observer;

import java.util.*;

public class ForecastDisplay implements Observer, DisplayElement {
	private float currentPressure = 29.92f;  
	private float lastPressure;
	private WeatherData weatherData;

	public ForecastDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}

	public void update(float temp, float humidity, float pressure) {
                lastPressure = currentPressure;
		currentPressure = pressure;

		display();
	}

	public void display() {
		System.out.print("Forecast: ");
		if (currentPressure > lastPressure) {
			System.out.println("Improving weather on the way!");
		} else if (currentPressure == lastPressure) {
			System.out.println("More of the same");
		} else if (currentPressure < lastPressure) {
			System.out.println("Watch out for cooler, rainy weather");
		}
	}
}


package observer;

import java.util.*;

public class StatisticsDisplay implements Observer, DisplayElement {
	private float maxTemp = 0.0f;
	private float minTemp = 200;
	private float tempSum= 0.0f;
	private int numReadings;
	private WeatherData weatherData;

	public StatisticsDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}

	public void update(float temp, float humidity, float pressure) {
		tempSum += temp;
		numReadings++;

		if (temp > maxTemp) {
			maxTemp = temp;
		}
 
		if (temp < minTemp) {
			minTemp = temp;
		}

		display();
	}

	public void display() {
		System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
			+ "/" + maxTemp + "/" + minTemp);
	}
}

4. 測試, 創建不同的觀察者(observer), 並把主題(subject)作爲參數傳入, 通知觀察者.


代碼:

  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public class WeatherStation {  
  11.   
  12.     /** 
  13.      * @param args 
  14.      */  
  15.     public static void main(String[] args) {  
  16.         // TODO Auto-generated method stub  
  17.         WeatherData weatherData = new WeatherData();  
  18.           
  19.         CurrentConditionsDisplay currentConditionsDisplay =   
  20.                 new CurrentConditionsDisplay(weatherData); //new的時候進行註冊  
  21.           
  22.         StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);  
  23.         ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);  
  24.           
  25.         weatherData.setMeasurements(806530.4f);  
  26.         weatherData.setMeasurements(827029.2f);  
  27.         weatherData.setMeasurements(789029.2f);  
  28.     }  
  29.   
  30. }  
/**
 * @time 2014年5月22日
 */
package observer;

/**
 * @author C.L.Wang
 *
 */
public class WeatherStation {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WeatherData weatherData = new WeatherData();
		
		CurrentConditionsDisplay currentConditionsDisplay = 
				new CurrentConditionsDisplay(weatherData); //new的時候進行註冊
		
		StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
		ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
		
		weatherData.setMeasurements(80, 65, 30.4f);
		weatherData.setMeasurements(82, 70, 29.2f);
		weatherData.setMeasurements(78, 90, 29.2f);
	}

}

5. 輸出:

  1. Current conditions: 80.0F degrees and 65.0% humidity  
  2. Avg/Max/Min temperature = 80.0/80.0/80.0  
  3. Forecast: Improving weather on the way!  
  4. Current conditions: 82.0F degrees and 70.0% humidity  
  5. Avg/Max/Min temperature = 81.0/82.0/80.0  
  6. Forecast: Watch out for cooler, rainy weather  
  7. Current conditions: 78.0F degrees and 90.0% humidity  
  8. Avg/Max/Min temperature = 80.0/82.0/78.0  
  9. Forecast: More of the same  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章