设计模式——行为型——观察者模式ObserverPattern

在ObserverPattern中,有一个Subject主题,多个Observer通过attach操作注册到Subject,是一对多的关系。
当Subject的状态改变时,通过notify机制通知所有Observer,通知方式通常是调用Observer的某个方法。
当Observer不再关注Subject的状态时,可以通过detach方法取消注册。

ObserverPattern的类图如下图所示:
在这里插入图片描述
ObserverPattern的时序图如下:
在这里插入图片描述
借用wiki上的代码:

class EventSource { // Subject接口
	public interface Observer { // Observer接口,
		void update(String event);
	}

	private final List<Observer> observers = new ArrayList<>(); // Subject维护一组Observer
	private void notify(String event) { // notify操作不会直接更新Observer的状态,而是通知Observers,调用其update操作进行相应的更新,实现了Subject和Observer的解耦
		observers.forEach(observer -> observer.update(event));
	}
	
	public void attach(Observer observer) { // 注册Observer
		observers.add(observer);
	}
	public void detach(Observer observer) { // 取消Observer
		observers.remove(observer);
	}
	
	public void scanSystemIn() { // scanner读取输入,引起状态改变,进而通知Observers
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			notify(line);
		}
	}
}
public class ObserverDemo {
	public static void main(String[] args) {
		sout("Enter Text: ");
		EventSource eventSource = new EventSource; // 创建Subject
		
		eventSource.attach(event -> { sout("Received response: " + event); }); // 匿名的Observer
		
		eventSource.scanSystemIn(); 
	}
}

从JDK1.0起,原生支持了ObserverPattern,位于java.util包中,其类图如下:
在这里插入图片描述

Observer接口比较简单,update方法接收被观察者Observable和参数Object:

public interface Observer {
	void update(Observable o, Object arg);
}

Observable类使用一个Vector维护一组Observer,使用boolean变量changed标记状态是否发生变化,如果changed=false,notify方法不再通知到Observer。

public class Observable {
	private boolean changed = false;
	private Vector<Observer> obs;
	public Observable() { obs = new Vector<>(); }
	// 添加和移除Observer
	public synchronized void addObserver(Observer o) {
		if (o == null) { throw new NPE(); }
		if (!obs.contains(o)) {
			obs.addElement(o);
		}
	}
	public synchronized void deleteObserver(Observer o) {
		obs.removeElement(o);
	} 
	// notify
	public void notifyObservers() { notifyObservers(null); }
	public void notifyObservers(Object arg) {
		Object[] arrLocal;
		synchronized (this) {
			if (!changed) { return; }
			arrLocal = obs.toArray();
			clearChanged();
		}
		for (int i = arrLocal.length - 1; i >= 0; i--) {
			((Observer) arrLocal[i]).update(this, arg);
		}
	}
	// 清空Observer
	public synchronized void deleteObservers() { obs.removeAllElements(); }
	// getter/setter
	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(); }
}

使用jdk原生接口实现一个ObserverPattern模式的例子:
首先是Observable:

public class DataStore extends Observable {
	private String data; // data即是Observable的状态
	public String getData() { return data; }
	public void setData(String data) {
		this.data = data;
		setChanged(); // 父类Observable定义的方法,标记changed,但不notify
	}
}

然后是Observer:

public class Screen implements Observer {
	@Override
	void update(Observable o, Object arg) { 
		// Observer的响应操作
	}
}

业务类:

public class ObserverDemo {
	public static void main(String[] args) {
		Screen screen = new Screen(); // 创建一个Observer
		DataStore dataStore = new DataStore(); // 创建一个Observable
		
		dataStore.addObserver(screen); // 注册Observer	

		dataStore.setData(data); // 更新Observable自身的状态
		
		dataStore.notifyObservers(); // 通知Observer
	}
}

参考:

  1. https://dzone.com/articles/design-patterns-uncovered
  2. https://en.wikipedia.org/wiki/Observer_pattern
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值