设计模式之观察者模式

Posted Sunzxyong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之观察者模式相关的知识,希望对你有一定的参考价值。

差不多一个月没更博了,主要是自己在写东西,今天写写android开发中比较重要的观察者设计模式
所谓观察者模式,就是一个是被观察的对象,一个是观察者对象,通过建立联系,即被观察的对象被观察者观察了,而当被观察的对象内部数据发生了改变时候,就会及时通知观察者,进而更新数据的显示。

举个栗子:
假如A是一个学生,他有一个名字,而B是显示该学生名字的界面,假如这时候有一个C界面有更改该学生的名字的操作,而如果要想B界面也同时更新该学生的名字,我们可以通过观察者模式来做,即把A设计成被观察的对象,B是观察者。这样我们在更新学生信息的时候,B界面也会同步更新。

要想实现观察者模式,我们知道必须要有观察者和被观察的对象。
而java中为我们提供了相应的Observable类和Observer接口供我们实现观察者模式:
都在util包下

java.util.Observable 被观察的对象
java.util.Observer 观察者

1、创建观察者

我们要观察某个对象数据是否发生改变,肯定需要指定当数据发生了改变时候需要在哪里更新数据的变化,即这个对象是观察者,让一个对象成为观察者,只需要实现Observer接口即可,同时需要实现一个方法update(),顾名思义,这个方法传入的就是发生了数据变化的对象

@Override
    public void update(Observable observable, Object o) 
    

2、创建被观察的对象

要向让一个对象成为具有被观察资格的对象,只需要继承自Observable类,这样该对象就可以被观察了,而Observable类中有几个重要的方法:

setChanged();//注明该对象发生了数据变化
notifyObservers();//提醒观察者更新数据
notifyObservers(Object data);//如果不想提醒所有观察了该对象的观察者都更新数据,可以传入个参数,可以理解为特定的Flag,而在观察者接收数据时候加个判断来保证只提醒指定的观察者更新数据
countObservers();//该对象被多少个观察者观察了
addObserver(Observer observer);//添加观察者
deleteObserver(Observer observer);//移除观察者

来看看源码通知某个观察者更新数据是怎么实现的:

List<Observer> observers = new ArrayList<Observer>();
boolean changed = false;

public void notifyObservers() 
        notifyObservers(null);
    
public void notifyObservers(Object data)    
    int size = 0;   
    Observer[] arrays = null;   
    synchronized (this)    
        if (hasChanged())    
            clearChanged();   
            size = observers.size();  
            arrays = new Observer[size];   
            observers.toArray(arrays);   
           
       
    if (arrays != null)    
        for (Observer observer : arrays)    
            observer.update(this, data);   
           
      

这里主要就是把监听了该对象的观察者都遍历一遍,调用观察者的observer.update(this, data); 方法进行被观察对象的传递,此时你可能发现该update方法正式刚刚我们实现Observer接口穿建观察者所实现的方法,其中第二个参数就是data,所以想要只提醒某个观察者更新数据变化,只需要传入个data(data定义),然后在观察者中用if判断即可:

public class MyObserver implements Observer 
    @Override
    public void update(Observable observable, Object o) 
        if(((String)o).equals("needupdate"))
            MyObservable myObservable = (MyObservable) observable;
            Log.v("zxy","new name = "+myObservable.getName());
        
    

3、让观察者观察需要观察的对象

观察者和被观察者创建好了,那么就需要被观察的对象让观察者进行观察了,而通过api发现被观察对象中有一个方法是添加观察者的:

public void addObserver(Observer observer) 
        if (observer == null) 
            throw new NullPointerException("observer == null");
        
        synchronized (this) 
            if (!observers.contains(observer))
                observers.add(observer);
        
    

所以可以通过该方法为该对象添加观察者

Demo

/**
 * 被观察的类
 */
public class MyObservable extends Observable 
    private String name="";

    public String getName() 
        return name;
    

    public void setName(String name) 
        if(!this.name.equals(name))
            this.name = name;
            setChanged();//标志数据已经改变,内部是通过一个布尔类型的flag作为判断数据是否发生变化
            notifyObservers();//提醒观察者更新数据

        
    
/**
 * 观察者类
 */
public class MyObserver implements Observer 

    /**
     * 添加新的需要被观察的类
     *
     * @param observable
     */
    public void addNewObservable(Observable observable) 
        observable.addObserver(this);
    

    @Override
    public void update(Observable observable, Object o) 
        MyObservable myObservable = (MyObservable) observable;
        Log.v("zxy", "new name = " + myObservable.getName());

    

这里我把添加观察者的方法封装在观察者内部

【注意】其中使用观察者模式需要注意一个问题,在Observer对象销毁前一定要用deleteObserver将其从列表中删除,也就是在onDestroy()方法中调用deleteObserver()方法。不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误。

以上是关于设计模式之观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

设计思想与模式之五观察者模式

PHP设计模式之----观察者模式

Head First设计模式之观察者模式

设计模式之观察者模式

设计模式系列之四:观察者模式

深入 Laravel 内核之观察者模式