一、观察者模式
观察者模式,又称发布订阅模式,定义对象之间的一对多关系,即多个观察者观察同时监视这被观察对象的状态,一旦被观察者发生变化,所有观察者(即依赖于此对象的)全部进行更新。例如,拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
二、Java中的观察者模式
Java中提供Observer接口和Observable类分别表示观察者和被观察者,其中Observable类包含addObserver(Observer o)添加观察者的方法、setChanged()设置被观察对象发生变化、notifyObservers(Object product)通知观察者,并将更新传递。
三、实例
本实例被观察者具有一个ArrayList的成员域,我们实现对该列表增加的同时,若干观察者对象也能收到更新,并作出响应。
被观察者类需要继承Observable类:
import java.util.ArrayList; import java.util.Observable; import java.util.Observer; public class ProductList extends Observable { private ArrayList<String> list = new ArrayList<>(); //被观察清单 private static ProductList p = null; //本类私有实例 private ProductList() //构造函数,意味着该类不能在外部实例化 { } public static ProductList getInstace() //获取该实例 { if(p==null) p = new ProductList(); return p; } @Override public synchronized void addObserver(Observer o) { //重写addObserver方法 super.addObserver(o); System.err.println("增加观察者"+o.toString()); } public void addProduct(String s) //成员方法,增加被观察对象清单 { list.add(s); System.err.println("增加被观察者"+s); this.setChanged(); this.notifyObservers(s); } }
两个观察者类分别实现Observer接口,重写update方法,即收到更新后的应对反应
import java.util.Observable; import java.util.Observer; public class AObserver implements Observer { private String name; AObserver(String s) { name = s; } @Override public void update(Observable o, Object arg) { String s = (String) arg; System.err.println("产品"+s+"被"+name+"观察到"); } public String toString() { return name; } }
import java.util.Observable; import java.util.Observer; public class BObserver implements Observer { String name; public BObserver(String name) { this.name=name; } @Override public void update(Observable o, Object arg) { String s = (String) arg; System.err.println("产品"+s+"被"+name+"观察到"); } public String toString() { return name; } }
主类实现观察者类和被观察者类的实例化,并对被观察清单做出添加动作。
public class Main { public static void main(String []args) { AObserver a = new AObserver("AAA"); BObserver b = new BObserver("BBB"); ProductList p = ProductList.getInstace(); p.addObserver(a); p.addObserver(b); p.addProduct("mgcosH"); } }
实验结果:
自己关于观察者模式的一个问题
如何在只有一个update方法的情况下使用不同的反应方式应对不同的被观察者更新,例如增加清单和删除清单应激方式不同?或者说有这种需要吗??