观察者——对象行为模式

来源:互联网 发布:为什么中国网络要翻墙 编辑:程序博客网 时间:2024/06/06 06:37

意图

又被称为发布-订阅Subscribe模式、模型-视图View模式、源-收听者Listener模式或从属者模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。


动机

将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。


适用场景

当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。

一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。


结构图

这里写图片描述

角色

抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。

具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。

具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。


实现

//观察者,需要用到观察者模式的类需实现此接口public interface Observer{    void update(Object...objs);}//被观察者(一个抽象类,方便扩展)public abstract class Observable{    public finalArrayList<Class<?>> obserList = new ArrayList<Class<?>>();    /**AttachObserver(通过实例注册观察者)    *<b>Notice:</b>obcan'tbenull,oritwillthrowNullPointerException    **/    public<T> void registerObserver(Tob){        if(ob==null) throw new NullPointerException();        this.registerObserver(ob.getClass());    }    /**    *AttachObserver(通过Class注册观察者)    *@paramcls    */    public void registerObserver(Class<?>cls){        if(cls==null) throw new NullPointerException();        synchronized(obserList){            if(!obserList.contains(cls)){                obserList.add(cls);            }        }    }    /**UnattachObserver(注销观察者)    *<b>Notice:</b>    *<b>ItreverseswithattachObserver()method</b>    **/    public<T>void unRegisterObserver(Tob){        if(ob==null) throw new NullPointerException();        this.unRegisterObserver(ob.getClass());    }    /**UnattachObserver(注销观察者,有时候在未获取到实例使用)    *<b>Notice:</b>    *<b>ItreverseswithattachObserver()method</b>    **/    public void unRegisterObserver(Class<?>cls){        if(cls==null) throw new NullPointerException();        synchronized(obserList){            Iterator<Class<?>>iterator=obserList.iterator();            while(iterator.hasNext()){                if(iterator.next().getName().equals(cls.getName())){                    iterator.remove();                    break;                }            }        }    }    /**detachallobservers*/    public void unRegisterAll(){        synchronized(obserList){            obserList.clear();        }    }    /**Ruturnthesizeofobservers*/    public int countObservers(){        synchronized(obserList){            returnobserList.size();        }    }    /**    *notify all observer(通知所有观察者,在子类中实现)    *@paramobjs    */    public abstract void notifyObservers(Object... objs);    /**    *notify one certain observer(通知某一个确定的观察者)    *@paramcls    *@paramobjs    */    public abstract void notifyObserver(Class<?> cls, Object... objs);    /**    *notifyonecertainobserver    *@paramcls    *@paramobjs    */    public abstract<T> void notifyObserver(T t, Object... objs);}//目标被观察者public class ConcreteObservable extends Observable{    private static ConcreteObservableinstance = null;    private ConcreteObservable(){};    public static synchronized ConcreteObservablegetInstance(){        if(instance == null){            instance=newConcreteObservable();        }        returninstance;    }    @Override    public <T> void notifyObserver(T t, Object... objs){        if(t == null) throw new NullPointerException();        this.notifyObserver(t.getClass(), objs);    }    @Override    public void notifyObservers(Object... objs){        for(Class<?>cls : obserList){            this.notifyObserver(cls, objs);        }    }    //通过java反射机制实现调用    @Override    public void notifyObserver(Class<?>cls, Object...objs){        if(cls == null) throw new NullPointerException();        Method[] methods = cls.getDeclaredMethods();        for(Method method : methods){            if(method.getName().equals("update")){                try{                    method.invoke(cls,objs);                    break;                }catch(IllegalArgumentException e){                    e.printStackTrace();                }catch(IllegalAccessException e){                    e.printStackTrace();                }catch(InvocationTargetException e){                    e.printStackTrace();                }            }        }    }}//使用(实现Observer接口)public class Text extends Activity implements Observer{    publicvoidonCreate(...){        ConcreteObservable.getInstance().registerObserver(Text.class);        ....    }    //实现接口处理    publicvoidupdate(Object...objs){        //做操作,比如更新数据,更新UI等    }}

优缺点

优点

  第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

 第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

缺点

  第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

  第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

  第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

  第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

0 0
原创粉丝点击