观察者模式典型实现方式:
1、定义2个接口:观察者(通知)接口、被观察者(主题)接口
2、定义2个类,观察者对象实现观察者接口、主题类实现被观者接口
3、主题类注册自己需要通知的观察者
4、主题类某个业务逻辑发生时通知观察者对象,每个观察者执行自己的业务逻辑。
类图
参考代码
package org.test.Observer;
public interface Observer {
/**
* 观察者类
* @param temp
* @param humidity
* @param pressure
*/
void update(float temp,float humidity,float pressure);
}
package org.test.Observer;
//被观察者-主题公园类..名字应该改下,,不过人懒
public interface Subject {
void removeObserver(Observer observer);
void addObserver(Observer observer);
void notifyObserver();
}
package org.test.Observer;
//display
public interface DisplayElement {
void display();
}
package org.test.Observer;
//天气数据中心-被观察者的实现类
import java.util.ArrayList;
import java.util.List;
public class WeatherData implements Subject {
private final List<Observer> lObserver = new ArrayList<Observer>();
private float temperature;
private float humidity;
private float pressure;
// java.util.Observer
@Override
public void removeObserver(Observer observer) {
// lObserver.remove(observer);
int i = lObserver.indexOf(observer);
if (i>=0){
lObserver.remove(i);
}else{
System.out.println("empty list");
}
}
@Override
public void addObserver(Observer observer) {
lObserver.add(observer);
}
@Override
public void notifyObserver() {
for(Observer o:lObserver){
o.update(temperature, humidity, pressure);
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
//super();
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
private void measurementsChanged() {
notifyObserver();
}
//others
}
package org.test.Observer;
//观察者实现类,current
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.addObserver(this);//加入消息收听队列
}
@Override
public void display() {
System.out.println("current conditions:" + temperature + "F degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
}
package org.test.Observer;
//观察者实现类
public class StatisticsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public StatisticsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.addObserver(this);
}
@Override
public void display() {
System.out.println("statistice conditions:" + temperature + "F degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
}
package org.test.Observer;
//main
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisDisplay = new StatisticsDisplay(weatherData);
weatherData.setMeasurements(80, 12, 30.4f);
weatherData.setMeasurements(70, 45, 45f);
}
}
JDK自带观察者模式
java.util.Observer观察者接口
package java.util;
/**
* A class can implement the <code>Observer</code> interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
java.util.Observable被观察者具体类
package java.util;
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
/* We don't want the Observer doing callbacks into
* arbitrary code while holding its own Monitor.
* The code where we extract each Observable from
* the Vector and store the state of the Observer
* needs synchronization, but notifying observers
* does not (should not). The worst result of any
* potential race-condition here is that:
* 1) a newly-added Observer will miss a
* notification in progress
* 2) a recently unregistered Observer will be
* wrongly notified when it doesn't care
*/
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
测试Demo
package org.test.Observer.ByJdk;
//图文信息对象
import java.util.Observable;
import java.util.Observer;
public class PicMessage extends Observable {
private String title = "";
private double size = 0.0;
public String getTitle() {
return title;
}
public double getSize() {
return size;
}
public void updateMessage(String title,double size){
this.title =title;
this.size = size;
}
public void subscription(Observer o){
addObserver(o);
}
public void modifyPrice(PicMessage pm){
setChanged();
notifyObservers(pm);
}
}
package org.test.Observer.ByJdk;
//观察者手机端
import java.util.Observable;
import java.util.Observer;
public class PhoneLogon implements Observer {
private String username = "";
public PhoneLogon(String username) {
this.username = username;
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
PicMessage pm = (PicMessage)arg;
System.out.println(username+"在手机登陆,点击查看《"+pm.getTitle()+"》,信息长度:"+pm.getSize());
}
}
package org.test.Observer.ByJdk;
//观察者PC端
import java.util.Observable;
import java.util.Observer;
public class PCLogon implements Observer {
private String username = "";
public PCLogon(String username) {
this.username = username;
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
PicMessage pm = (PicMessage)arg;
System.out.println(username+"在电脑登陆,点击查看《"+pm.getTitle()+"》图文信息,长度:"+pm.getSize());
}
}
package org.test.Observer.ByJdk;
//测试代码
import java.util.Observer;
public class Demo {
public static void main(String[] args) throws InterruptedException {
PicMessage pm = new PicMessage();
pm.updateMessage("我们公司上市了", 5.0);
pm.subscription(new PCLogon("haoren"));
pm.subscription(new PCLogon("huairen"));
pm.subscription(new PhoneLogon("haoren"));
pm.modifyPrice(pm);
}
}