观察者模式要求当某一个主题Subject对象的某一个状态发生变化时,能够通知其他的对象,当然因为主题要通知其他对象,则主题本身需要提供注入观察者角色对象的入口,即主题需要有对该主题对象感兴趣的对象的引用,当主题的某个状态发生变化,即某个观察者对象感兴趣的状态发生变化,则主题就可以直接通知观察者对象了。
下面提供一个上面类图的参考代码:
抽象主题角色Subject的代码如下:
public interface Subject
{
//添加观察者
public void attach(Observerobserver);
//取消观察者
public void detach(Observerobserver);
//对观察者进行通知
void notifyObservers();
}
具体主题ConcreteSubject的代码如下:
public class ConcreteSubject implements Subject
{
private Vector observersVector = new java.util.Vector();
public void attach(Observerobserver)
{
observersVector.addElement(observer);
}
public void detach(Observerobserver)
{
observersVector.removeElement(observer);
}
public void notifyObservers()
{
java.util.Enumerationenumeration = observers();
while(enumeration.hasMoreElements())
{
((Observer)enumeration.nextElement()).update();
}
}
public Enumerationobservers()
{
return ((java.util.Vector)observersVector.clone()).elements();
}
}
注意上面的observers()方法给出的Enumeration对象是聚集的一个拷贝,是为了使外界不能修改主题自己所使用的对象。
抽象观察者角色Observer的代码如下:
public interface Observer
{
//观察者起作用的方法,实际使用中,可以传入参数。
void update();
}
虽然这里提供的是update方法中没有参数,但在实际情况下,通常是需要参数传入的。
具体观察者角色ConcreteObserver的代码如下:
public class ConcreteObserver implements Observer
{
public void update()
{
// Write your code here
}
}
另外关于具体主题中的聚集对象,也是可以将其上移至抽象主题角色中的,此时Subject就不应该为一个接口,而是一个抽象类。比如按下图的方式进行实现,这种方式可能更为常用。
此时的Subject为一个抽象类。当ConcreteSubject某个状态改变时,则其调用notifyObservers方法进行通知观察者。
观察者模式与责任链模式的区别,观察者模式中的所有观察者彼此之间的地位是平等的,都是平等地对某一个消息进行响应,而责任链中虽然也有多个对象对某一消息进行响应,但是其彼此关系是不平等的,某一个对象依赖于其调用对象的引用。即观察者模式中观察者对象的调用是由主题角色进行平等调用的,而责任链模式中的责任对象则是由引用它的责任对象进行调用的,那么引用对象既可以调用也可以不调用。