每天一个设计模式(2):观察者模式

2.观察者模式

  观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

一.要点

  •  观察者模式定义了对象之间的一对多的关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
  •  主题(被观察者)通过一个共同的接口来更新观察者。
  •  有多个观察者时,不可以依赖特定的通知次序。
  •  观察者模式提供了一种对象设计,让主题和观察者之间松耦合。改变主题或者观察者其中一方,并不会影响另一方。
  •  使用此模式时,可以从被观察者处推(push)或拉(pull)数据。
  •    Java有多种观察者模式的实现,包括了通用的java.util.Observable。
  •    如果有必要的话,可以实现自己的Observable。
  •    在JavaBeans和Swing中,也都实现了观察者模式。

二.设计原则

 1.当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

  当有新的具体类需要作为观察者时,要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。

 2.找出程序中会变化的方面,然后将其和固定不变的方面相分离。

  在观察者模式中,会改变的是主体的状态,以及观察者的数目和类型。用这个模式,你可以改变依赖于主题状态的的对象,却不必改变主题。这就叫提前规则!

 3.针对接口编程,不针对实现编程。

  主题和观察者都是用接口,观察者利用主题的接口向主题注册,而主题利用观察者的而接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点。

 4.多用组合,少用继承。

  观察者模式利用“组合”将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合方式而产生的。

三.UML关系图

  图中,MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。

四.Java内置的观察者模式

  主题(被观察者):扩展自java.util.Observable。(因为是类,所以存在一定的局限性)。

  观察者:实现java.util.Observer接口。

通过调用Observable对象的addObserver()和deleteObserver()方法添加或者删除观察者。

  被观察者送出通知时,需要两个步骤:

  1.调用setChanged()方法,标记状态已经改变的事实;

  2.调用两种notifyObservers()方法中的一个:

  notifyObservers()或notifyObservers(Object arg):当通知时,后者的版本可以传送任何的数据对象给每一个观察者。

  观察者接收通知:

  update(Observable o, Object arg)

  主题本身是第一个参数,第二个参数为notifyObservers(Object arg)的数据对象,如果没有则为空。

  Java内置的Observer模式支持push和pull两种数据传递方式:

  push:由被观察者把数据推给观察者。

  pull:观察者从被观察者中拉数据。

五.实现代码

一个Observer接口:

public interface Observer {  
    public void update();  
}  

一个实现类:

public class Observer1 implements Observer {  
  
    @Override  
    public void update() {  
        System.out.println("observer1 has received!");  
    }  
}  

Subject接口:

public interface Subject {  
      
    /*增加观察者*/  
    public void add(Observer observer);  
      
    /*删除观察者*/  
    public void del(Observer observer);  
      
    /*通知所有的观察者*/  
    public void notifyObservers();  
      
    /*自身的操作*/  
    public void operation();  
}  

Subject实现类:

public abstract class AbstractSubject implements Subject {  
  
    private Vector<Observer> vector = new Vector<Observer>();  
    @Override  
    public void add(Observer observer) {  
        vector.add(observer);  
    }  
  
    @Override  
    public void del(Observer observer) {  
        vector.remove(observer);  
    }  
  
    @Override  
    public void notifyObservers() {  
        Enumeration<Observer> enumo = vector.elements();  
        while(enumo.hasMoreElements()){  
            enumo.nextElement().update();  
        }  
    }  
}  


public class MySubject extends AbstractSubject {  
  
    @Override  
    public void operation() {  
        System.out.println("update self!");  
        notifyObservers();  
    }  
  
}  

测试类:

public class ObserverTest {  
  
    public static void main(String[] args) {  
        Subject sub = new MySubject();  
        sub.add(new Observer1());   
          
        sub.operation();  
    }  
  
}  

输出:

update self!
observer1 has received!

参考:

《Head Frist 设计模式》

http://blog.csdn.net/zhangerqing/article/details/8243942

http://www.cnblogs.com/mengdd/archive/2013/01/03/2843298.html

原文地址:https://www.cnblogs.com/Eason-S/p/5660209.html