转自:http://blog.csdn.net/lansuiyun/article/details/11396815
观察者模式又名发布-订阅模式,定义了对象之间的一对多依赖,多个对象同时监听一个对象,当被监听对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新,被监听对象称为主题suject,监听对象称为观察者observer。
观察者模式结构如下(网上找的图):
简单来说,observer必须实现update方法,来接收suject状态变化时的通知及更新。suject维护一个observer列表,在状态变化时会逐个的调用observer的update方法来通知、更新observer,为此,suject须提供注册(添加observer到列表)、删除、通知更新三个方法。
观察者模式又分为两种模式:push和pull。push是指suject在状态变化时将所有的状态信息都发给observer,pull则是suject通知observer更新时,observer获取自己感兴趣的状态。
两种模式在实现上的区别:push模式下,observer的update方法接收的是状态信息,而pull模式下,update方法接收的是suject对象,这种情况下,suject须提供状态信息的get方法,让observer可以获取自己感兴趣的信息。
两种模式的优劣:push模式要求suject必须了解observer需要的状态,pull则是observer按需获取;push模式下observer的update方法的参数是具体的状态信息,发生变化时必须要重写update方法,pull模式则是将suject对象本身传给update,是最大的参数集合。
push模式具体实现:
- suject超类
- package observer.push;
- import java.util.LinkedList;
- import java.util.List;
- /**
- * 推模式主题超类,能够注册、删除、数据变动时通知关注者
- * @author sky
- *
- */
- public abstract class Subject {
- /**
- * 观察者名单
- */
- private List<Observer> list = new LinkedList<>();
- /**
- * 注册观察者
- * @param o 观察者
- */
- public void addObserver(Observer o){
- list.add(o);
- }
- /**
- * 删除观察者
- * @param o 观察者
- */
- public void deleteObserver(Observer o){
- int i = list.indexOf(o);
- if (i>-1) {
- list.remove(i);
- }
- }
- /**
- * 通知观察者
- */
- public void notifyObservers(String state){
- for (Observer o:list) {
- o.update(state);
- }
- }
- }
- observer接口
- package observer.push;
- /**
- * 推模式观察者接口
- * @author sky
- *
- */
- public interface Observer {
- public void update(String state);
- }
- suject具体实现类
- package observer.push;
- public class ConcreteSubject extends Subject {
- /**
- * 状态
- */
- public String state;
- /**
- * 状态是否改变的标志
- */
- public boolean isChanged = false;
- /**
- * 状态改变后,通知观察者
- */
- public void change(){
- if (isChanged) {
- this.notifyObservers(state);
- }
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- isChanged = true;
- }
- public boolean isChanged() {
- return isChanged;
- }
- public void setChanged(boolean isChanged) {
- this.isChanged = isChanged;
- }
- }
- observ具体实现类
- package observer.push;
- /**
- * 推模式观察者实现类
- * @author sky
- *
- */
- public class ConcreteObserver implements Observer {
- public String name;
- public ConcreteObserver(String n){
- name=n;
- }
- @Override
- public void update(String state) {
- System.out.println(name+" update new state:"+state);
- }
- }
- 测试类:
- package observer.push;
- public class Test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- ConcreteSubject subject = new ConcreteSubject();
- Observer o1 = new ConcreteObserver("张山");
- Observer o2 = new ConcreteObserver("李四");
- subject.addObserver(o1);
- subject.addObserver(o2);
- System.out.println("准备:");
- subject.setState("上班了");
- subject.change();
- subject.setState("下班了");
- subject.change();
- }
- }
- 输出:
- 准备:
- 张山 update new state:上班了
- 李四 update new state:上班了
- 张山 update new state:下班了
- 李四 update new state:下班了
pull模式实现:
- suject超类
- package observer.pull;
- import java.util.LinkedList;
- import java.util.List;
- /**
- * 拉模式主题超类,能够注册、删除、数据变动时通知关注者
- * @author sky
- *
- */
- public abstract class Subject {
- /**
- * 观察者名单
- */
- private List<Observer> list = new LinkedList<>();
- /**
- * 注册观察者
- * @param o 观察者
- */
- public void addObserver(Observer o){
- list.add(o);
- }
- /**
- * 删除观察者
- * @param o 观察者
- */
- public void deleteObserver(Observer o){
- int i = list.indexOf(o);
- if (i>-1) {
- list.remove(i);
- }
- }
- /**
- * 通知观察者
- */
- public void notifyObservers(){
- for (Observer o:list) {
- o.update(this);
- }
- }
- }
- observer接口
- package observer.pull;
- /**
- * 拉模式观察者接口
- * @author sky
- *
- */
- public interface Observer {
- public void update(Subject s);
- }
- suject具体实现类
- package observer.pull;
- public class ConcreteSubject extends Subject {
- /**
- * 状态
- */
- public String state;
- /**
- * 状态是否改变的标志
- */
- public boolean isChanged = false;
- /**
- * 状态改变后,通知观察者
- */
- public void change(){
- if (isChanged) {
- this.notifyObservers();
- }
- }
- public String getState() {
- return state;
- }
- public void setState(String state) {
- this.state = state;
- isChanged = true;
- }
- public boolean isChanged() {
- return isChanged;
- }
- public void setChanged(boolean isChanged) {
- this.isChanged = isChanged;
- }
- }
- observer具体实现类
- package observer.pull;
- /**
- * 拉模式观察者实现类
- * @author sky
- *
- */
- public class ConcreteObserver implements Observer {
- public String name;
- public ConcreteObserver(String n){
- name=n;
- }
- @Override
- public void update(Subject s) {
- String state = ((ConcreteSubject)s).getState();
- System.out.println(name+" update new state:"+state);
- }
- }
- 测试类
- package observer.pull;
- public class Test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- ConcreteSubject subject = new ConcreteSubject();
- Observer o1 = new ConcreteObserver("张山");
- Observer o2 = new ConcreteObserver("李四");
- subject.addObserver(o1);
- subject.addObserver(o2);
- System.out.println("pull模式准备:");
- subject.setState("上班了");
- subject.change();
- subject.setState("下班了");
- subject.change();
- }
- }
- 输出
- pull模式准备:
- 张山 update new state:上班了
- 李四 update new state:上班了
- 张山 update new state:下
定义对象间的一种一对多的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。
观察者模式其实就是为了解偶,如果按你所说的直接通知的话,那你就需要获得该对像的引用,如果那天你的程序需要实现别外一种订阅(非用户)那就就需要更改代码了,这就违背了开-闭原则,利用观察者模式的话就只需实现监听器接口,并加入即可。