前言
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
认识观察者模式
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
应用实例:我们举个例子来理解一下观察者模式的含义,1、我们都在新浪微博中关注过某一位明星,每当这位明星发布一条动态时候,他的粉丝就都会知道。2、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
使用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
模型实现:分为两种:手动实现或利用Java提供的Observer接口和Observable类实现观察者模式
①手动实现
观察者模式又被称为发布-订阅(Publish/Subscribe)模式,所以我们创建 Subject 类作为发布类、Observer 抽象类作为观察者和扩展了抽象类 Observer 的实体类。
步骤 1:创建 Subject 类。
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
步骤 2:创建 Observer 类。
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
步骤 3:创建实体观察者类。
public class OneObserver extends Observer{
public OneObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "OneObserver String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class SecObserver extends Observer{
public SecObserver (Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "SecObserver String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
运行:
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new OneObserver(subject);
new SecObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
②Java提供的Observer接口和Observable类实现观察者模式
对于观察者模式,其实Java已经为我们提供了已有的接口和类。接下来我们来看看是如何利用Java提供的接口和方法来实现观察者模式。
JDK源码如下:
1 package java.util;
2
3 public interface Observer {
4 void update(Observable o, Object arg);
5 }
1 package java.util;
2
3 public class Observable {
4 private boolean changed = false; //是否改变状态
5 private Vector obs; //Vector利用同步方法来线程安全,线程安全在多线程情况下不会造成数据混乱
6
7 public Observable() {
8 obs = new Vector();
9 }
10
11 public synchronized void addObserver(Observer o) {
12 if (o == null)
13 throw new NullPointerException();
14 if (!obs.contains(o)) {
15 obs.addElement(o);
16 }
17 }
18
19 public synchronized void deleteObserver(Observer o) {
20 obs.removeElement(o);
21 }
22
23 public void notifyObservers() {
24 notifyObservers(null);
25 }
26
27 public void notifyObservers(Object arg) {
28 Object[] arrLocal;
29
30 synchronized (this) {
31 if (!changed) //状态值未改变时返回,不通知
32 return;
33 arrLocal = obs.toArray(); //将Vector转换成数组
34 clearChanged(); //重置状态
35 }
36
37 for (int i = arrLocal.length-1; i>=0; i--)
38 ((Observer)arrLocal[i]).update(this, arg);
39 }
40
41 public synchronized void deleteObservers() {
42 obs.removeAllElements();
43 }
44
45 protected synchronized void setChanged() {
46 changed = true;
47 }
48
49 protected synchronized void clearChanged() {
50 changed = false;
51 }
52
53 public synchronized boolean hasChanged() {
54 return changed;
55 }
56
57 public synchronized int countObservers() {
58 return obs.size();
59 }
60 }
Observable 对应 发布者,Observer 对应 观察者。既然jdk通过了,我们直接实现就可以了。
/**
* 1、实现java.util.Observer接口的观察者
*
*/
public class Subscribe implements Observer {
public Subscribe(Observable o){
o.addObserver(this); //将该观察者放入待通知观察者里
}
/* (non-Javadoc)
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(Observable o, Object arg) {
System.out.println("收到通知:" + ((Publish)o).getData());
}
}
/**
* 2、继承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(); //调用父类Observable方法,通知所有观察者
}
}
运行:
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Publish publish = new Publish();
Subscribe subscribe = new Subscribe(publish);
publish.setData("开始");
}
}
注:观察者模式是很常用一种模式,掌握是必须的。