写在模式学习之前
什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。
设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许你根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以“模式专家”的角度来看,都是最佳的设计,不得不说是“最佳的模式实践”,这是因为你积累了很多的实践经验,知道“在什么场合代码应该怎么写”,这本身就是设计模式。
有人说:“水平没到,学也白学,水平到了,无师自通”。诚然,模式背熟,依然可能写不出好代码,更别说设计出好框架;OOP理解及实践经验到达一定水平,同时也意味着总结了很多好的设计经验,但"无师自通",却也未必尽然,或者可以说,恰恰是在水平和经验的基础上,到了该系统的学习一下“模式”的时候了,学习一下专家总结的结果,印证一下自己的不足,对于提高水平还是很有帮助的。
本系列的设计模式学习笔记,实际是对于《Java与模式》这本书的学习记录。
观察者模式的定义
观察者模式,又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式、从属者(Dependerts)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同事监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新。
观察者模式的 结构
结构图

所涉及的角色
(1)抽象主题(Subject)角色:主题角色吧所有对观察者对象的引用保存在一个聚集(比如Vector对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。
(2)抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。
(3)具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现,负责实现如何 引用观察者的聚集的管理办法。
(4)具体观察者(ConcreteObserver)角色:存储于主题的状态自洽的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
代码实现
import java.util.*;
interface Subject
{
//调用这个方法登记一个新的观察者对象
void attach(Observer observer);
//调用这个方法删除一个登记过的观察者对象
void detach(Observer observer);
//调用这个方法通知所有登记过的观察者对象
void notifyObservers();
}
class ConcreteSubject implements Subject
{
private Vector observersVector = new Vector();
public void attach(Observer observer)
{
observersVector.addElement(observer);
}
public void detach(Observer observer)
{
observersVector.removeElement(observer);
}
public void notifyObservers()
{
Enumeration e = observers();
while(e.hasMoreElements())
{
((Observer)e.nextElement()).update();
}
}
public Enumeration observers()
{
return ((Vector)observersVector.clone()).elements();
}
}
interface Observer
{
void update();
}
class ConcreteObserver implements Observer
{
public void update()
{
System.out.println("I am notified");
}
}
JDK对观察者模式的支持
JDK提供了java.util.Observable类和Observer接口,构成Java语言对观察者模式的支持。下面演示一个使用这两个接口/对象的例子。
结构图

代码实现
import java.util.Observer;
import java.util.Observable;
class Tester
{
private static Watched watched;
private static Observer watcher;
public static void main(String[] args)
{
//创建被观察者对象
watched = new Watched();
//创建观察者对象,并将被观察者对象登记
watcher = new Watcher(watched);
//给给观察者对象的状态赋值2次
watched.changeData("I am Tom");
watched.changeData("I am Jack");
}
}
class Watched extends Observable
{
private String data = "";
public String retrieveData()
{
return data;
}
public void changeData(String data)
{
if(!this.data.equals(data))
{
this.data = data;
setChanged();
}
notifyObservers();
}
}
class Watcher implements Observer
{
public Watcher(Watched w)
{
w.addObserver(this);
}
public void update(Observable ob,Object arg)
{
System.out.println("Data has been changed to: '" + ((Watched)ob).retrieveData() + "'");
}
}
Observable源码
我们也来看看JDK源码:jav