观察者模式在23中模式中应该算比较简单的一种,并没有太大的难度,属于一看就懂的那种。
一、什么是观察者模式
观察者模式又称订阅者模式,观察者模式定义了一种一对多的关系,即多个观察者同时观察被观察者对象。只要被观察者发生变化,所有的观察者就会知道,并自动更新自己。
二、举例说明
最近小米8发布了,那么肯定是会在京东卖,在淘宝卖,以及其他一些网站,那么就可以有以下伪代码
if(发布了新产品) {
推送产品到淘宝;
推送产品到京东;
......
}
可以看到这样会无限的加下去,代码耦合度高,不利于维护。
如果利用观察者模式,这个问题就能轻易解决了。
三、代码实现
先看看项目的目录,更清晰
我们首先先定义老东家小米,也就是被观察者
/**
* 观察者模式 被观察的商品列表
* 继承Observable接口
* @author liu
*/
public class ProductList extends Observable {
// 存放商品
private List productList = null;
// 使用单例模式,类的唯一实例
private static ProductList instance;
// 私有构造方法
private ProductList() {}
/**
* 返回类的唯一实例
* @return
*/
public static ProductList getInstance() {
if(instance == null) {
instance = new ProductList();
instance.productList = new ArrayList();
}
return instance;
}
/**
* 添加观察者
* @param observer 要被添加的观察者
*/
public void addProductListObserver(Observer observer) {
this.addObserver(observer);
}
/**
* 新增商品
* @param product
*/
public void addProduct(String product) {
// 把商品添加进商品列表
productList.add(product);
System.out.println("新增了商品:" + product);
// 标记被观察的对象已改变
this.setChanged();
// 通知观察者,并传递新产品
this.notifyObservers(product);
}
}
被观察者继承了Observable 类,在该类里有一些方法可以供被观察者使用。
我们调用了addObserver方法,该方法可以添加观察者,其实它是使用了一个容器去放观察者,源码如下
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
在addProduct方法中,我们调用了setChanged方法标志被观察者状态已经改变,源码如下
/**
* Marks this Observable object as having been changed; the
* hasChanged method will now return true.
*/
protected synchronized void setChanged() {
changed = true;
}
还调用了一个notifyObservers方法,该方法会通知观察者,我的状态已经改变。该方法源码如下
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);
}
可以看到在该方法中,调用了观察者实现的update方法(观察者实现的代码在下面)
接着定义马云,也就是观察者一
public class TaobaoObserver implements Observer {
@Override
public void update(Observable productList, Object product) {
String newProduct = (String)product;
System.out.println("发送新商品" + newProduct + "到淘宝商城");
}
}
观察者实现了Observer 接口,并实现了该接口中唯一的方法update,该方法在被观察者的状态改变后,就会调用,所以我们可以在这个方法里进行一些操作。
接下来定义刘强东,也就是观察者二
**
* 观察者 实现了Observer接口
* @author liu
*/
public class JDObserver implements Observer {
@Override
/**
* 只要改变了 observable 对象就调用此方法。
*/
public void update(Observable productList, Object product) {
// 获取改变的商品
String newProduct = (String)product;
System.out.println("发送新商品" + newProduct + "到京东商城");
}
}
一切准备就绪,我们现在来定义一个测试类
public class Test {
public static void main(String[] args) {
ProductList pl = ProductList.getInstance();
JDObserver observer1 = new JDObserver();
TaobaoObserver observer2 = new TaobaoObserver();
// 添加观察者
pl.addProductListObserver(observer1);
pl.addProductListObserver(observer2);
// 增加商品
pl.addProduct("小米8");
}
}
运行后输出
新增了商品:小米8
发送新商品小米8到淘宝商城
发送新商品小米8到京东商城
可以看到,雷军发布了小米8,马云和刘强东知道之后,马上会把小米8放到自己的网站售卖,实现了很好的协作方式。