天天看点

设计模式之观察者模式(Java实现)

    观察者模式是设计模式中常见的一种模式,他的思想犹如他的名字一样,就是想构建一个观察者观察他所关注的主题,当主题发生变化了,就会通知观察者。观察者模式也叫发布订阅模式,这种设计模式用在了很多地方,比如zookeeper的节点观察机制。

    这里我们构建一个如下模型,Subject<-AbstractSubject<-TopSubject  与 Observer<-Watcher,他们的关系如下图所示:

设计模式之观察者模式(Java实现)

通过java实现:

Observer.java

package com.xxx.design.watcher;

public interface Observer {
	void update();
}
           

Watcher.java

package com.xxx.design.watcher;
/**
 * 观察者
 *
 */
public class Watcher implements Observer {
	
	private String name;
	public Watcher(String name) {
		this.name = name;
	}

	@Override
	public void update() {
		System.out.println("watcher "+name+" update state.");
	}

}
           

Subject.java

package com.xxx.design.watcher;

public interface Subject {
	void add(Observer observer);
	void delete(Observer observer);
	void notifyObserver();
	void action();
}
           

AbstractSubject.java

package com.xxx.design.watcher;
import java.util.Enumeration;
import java.util.Vector;
public abstract class AbstractSubject implements Subject{
	private Vector<Observer> obs = new Vector<Observer>();
	
	@Override
	public void add(Observer observer) {
		obs.add(observer);
	}
	
	@Override
	public void delete(Observer observer) {
		obs.remove(observer);
	}
	
	@Override
	public void notifyObserver() {
		Enumeration<Observer> eles = obs.elements();
		while(eles.hasMoreElements()){
			eles.nextElement().update();
		}
	}
}
           

TopSubject.java

package com.xxx.design.watcher;

public class TopSubject extends AbstractSubject {

	@Override
	public void action() {
		System.out.println("i am a subject,update now.");
		notifyObserver();
	}
	
	public static void main(String[] args) {
		Subject subject = new TopSubject();
		subject.add(new Watcher("aa"));
		subject.add(new Watcher("bb"));
		subject.add(new Watcher("cc"));
		subject.action();
	}

}
           

    运行程序,打印结果如下:

i am a subject,update now.
watcher aa update state.
watcher bb update state.
watcher cc update state.
           

    观察者需要注意的是:避免循环引用,如果是顺序执行,考虑采用异步实现,避免因为一个处理异常导致整个系统卡壳。另外,现在java.util包中api已经提供了观察者模式的实现。我们可以利用Observable类和Observer接口来实现一个观察者模式:

Subscribe.java

package com.xxx.design.watcher.jdk;

import java.util.Observable;
import java.util.Observer;

public class Subscribe implements Observer {
	
	private String name;
	public Subscribe(String name){
		this.name = name;
	}
	
	public void add(Observable o){
		o.addObserver(this);
	}

	@Override
	public void update(Observable o, Object arg) {
		System.out.println(name+" 收到通知:"+((Publish)o).getData());
	}

}
           

Publish.java

package com.xxx.design.watcher.jdk;
import java.util.Observable;
public class Publish extends Observable {
	private String data = "";
	public String getData() {
		return data;
	}
	
	public void setData(String data) {
		if(!this.data.equals(data)){
			this.data = data;
			setChanged();
		}
		notifyObservers();
	}
	
	public static void main(String[] args) {
		Publish publish = new Publish();
		Subscribe subscribe = new Subscribe("aaa");
		subscribe.add(publish);
		Subscribe subscribe2 = new Subscribe("bbb");
		subscribe2.add(publish);
		publish.setData("start");
		publish.setData("end");
	}
}
           

运行程序,打印信息如下:

bbb 收到通知:start
aaa 收到通知:start
bbb 收到通知:end
aaa 收到通知:end