目录
1.核心思想
定义了一对多的关系,当一个对象的状态发生改变,依赖于他的对象也会收到通知改变。
2.成员
Subject(主题):
Subject是被观察的对象。它包含了一个观察者列表,可以增加或删除观察者对象。当它的状态发生变化时,会通知所有注册过的观察者。
Observer(观察者):
Observer是观察主题的对象。当观察的主题状态发生变化时,Observer会接收到通知并进行相应的更新操作。
3.优点
解耦性:主题和观察者之间是松耦合的,主题只知道观察者实现了特定的接口,不需要了解观察者的具体实现。
扩展性:可以灵活地增加新的观察者,或者移除现有的观察者,而不需要修改主题的代码。
支持广播通信:主题对象可以向所有注册的观察者同时发送通知,观察者收到通知后可以自行处理。
消息队列系统:发布-订阅模型中的订阅者即为观察者。
3.代码实现
3.1 主题接口和具体主题
public interface Subject {
void add(Observer observer);
void delete(Observer observer);
void update(String message);
}
public class ZookperSubject implements Subject{
private List<Observer> observerList = new ArrayList<Observer>();
@Override
public void add(Observer observer) {
observerList.add(observer);
}
@Override
public void delete(Observer observer) {
observerList.remove(observer);
}
@Override
public void update(String message) {
for (Observer observer : observerList) {
observer.attach(message);
}
}
}
3.2 观察者接口和具体观察者
public interface Observer {
void attach(String message);
}
public class ClientObserver implements Observer{
private String ip;
public ClientObserver(String ip) {
this.ip = ip;
}
@Override
public void attach(String message) {
System.out.println("客户端"+ip+message);
}
}
3.3 测试类
public class Test {
public static void main(String[] args) {
//创建注册中心
ZookperSubject zookperSubject = new ZookperSubject();
ClientObserver clientObserver = new ClientObserver("222.22.222.2");
zookperSubject.add(new ClientObserver("111.11.111.1"));
zookperSubject.add(clientObserver);
zookperSubject.add(new ClientObserver("333.33.333.3"));
zookperSubject.update("订阅");
zookperSubject.delete(clientObserver);
}
}
4.源码分析
4.1 Observable类
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;//线程安全的list
/** Construct an Observable with zero Observers. */
public Observable() {
obs = new Vector<>();
}
/**
* Adds an observer to the set of observers for this object, provided
* that it is not the same as some observer already in the set.
* The order in which notifications will be delivered to multiple
* observers is not specified. See the class comment.
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver(Observer o) {//新增观察者
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* Deletes an observer from the set of observers of this object.
* Passing <CODE>null</CODE> to this method will have no effect.
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
* If this object has changed, as indicated by the
* <code>hasChanged</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to
* indicate that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and <code>null</code>. In other
* words, this method is equivalent to:
* <blockquote><tt>
* notifyObservers(null)</tt></blockquote>
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers() {//通知方法
notifyObservers(null);
}
/**
* If this object has changed, as indicated by the
* <code>hasChanged</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to indicate
* that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and the <code>arg</code> argument.
*
* @param arg any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
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) //需要我们调用方法给值 setChanged
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);//update调用的是Observer接口实现的方法例子中的警察
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
public synchronized void deleteObservers() {//删除观察者
obs.removeAllElements();
}
/**
* Marks this <tt>Observable</tt> object as having been changed; the
* <tt>hasChanged</tt> method will now return <tt>true</tt>.
*/
protected synchronized void setChanged() {//update前更定状态
changed = true;
}
/**
* Indicates that this object has no longer changed, or that it has
* already notified all of its observers of its most recent change,
* so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
* This method is called automatically by the
* <code>notifyObservers</code> methods.
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged() {//取消通知
changed = false;
}
/**
* Tests if this object has changed.
*
* @return <code>true</code> if and only if the <code>setChanged</code>
* method has been called more recently than the
* <code>clearChanged</code> method on this object;
* <code>false</code> otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {//获取通知状态
return changed;
}
/**
* Returns the number of observers of this <tt>Observable</tt> object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {//获取观察者个数
return obs.size();
}
}
4.2 小偷类
public class Thief extends Observable {
private String name;
public Thief(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void steal(){
System.out.println(name +"动手了");
super.setChanged();//给观察者的前置状态
super.notifyObservers();
}
}
4.3 警察类
public class Police implements Observer {
private String name;
public Police(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("收手吧,"+((Thief)o).getName()+"外面都是警察");
}
}
4.4 测试类
public class Test {
public static void main(String[] args) {
Thief thief = new Thief("阿祖");
Police sir = new Police("sir");
thief.addObserver(sir);
thief.steal();
}
}