设计模式——观察者模式

来源:互联网 发布:淘宝宝贝卖点的列子 编辑:程序博客网 时间:2024/06/05 19:16

观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。(ps:其实本质上并不是自动更新,还是由主体来触发更新的)

设计原则:为了交互对象之间的松耦合设计而努力。

 

 1 package pattern.observer; 2  3 /** 4  * 主体公共接口 5  * @author CS_Xiaochao 6  * 7  */ 8 public interface Subject { 9     10     void registerObserver(Observers observers);11     void removeObserver(Observers observers);12     void notifyObserver(int tempurature);13     14 }
主体公共接口
 1 package pattern.observer; 2  3 import java.util.LinkedList; 4 import java.util.List; 5  6 /** 7  * 实现接口的一个主体 8  * @author CS_Xiaochao 9  *10  */11 public class WeatherData implements Subject {12     13     private Observers observers;14     private List<Observers> list;15     16     public WeatherData(){17         if(list == null){18             list = new LinkedList<Observers>();19         }20     }21 22     @Override23     public void registerObserver(Observers observers) {24         if(list.add(observers)){25             System.out.println("注册观察者:" + observers + " 成功!");26         }        27     }28 29     @Override30     public void removeObserver(Observers observers) {31         if(list.remove(observers)){32             System.out.println("注销观察者:" + observers + " 成功!");33         }34     }35 36     @Override37     public void notifyObserver(int tempurature) {38         for(int i = 0; i < list.size(); i++){39             list.get(i).update(tempurature);40         }41     }42 43 }
实现了主体接口的一个主体
 1 package pattern.observer; 2  3 /** 4  * 观察者公共接口 5  * @author CS_Xiaochao 6  * 7  */ 8 public interface Observers {     9     void update(double tempurature);10 }
观察者公共接口
 1 package pattern.observer; 2  3 public class TemperatureBoard implements Observers { 4  5     @Override 6     public void update(double tempurature) { 7         System.out.println("当前温度:" + tempurature); 8     } 9 10 }
观察者1
 1 package pattern.observer; 2  3 public class ComitityBoard implements Observers { 4  5     @Override 6     public void update(double tempurature) { 7         System.out.println("当前湿度为:" + Math.sqrt(tempurature)); 8     } 9 10 }
观察者2
 1 package pattern.observer; 2  3 import java.util.Random; 4  5 public class ObserverDemo { 6  7     /** 8      * @param args 9      */10     public static void main(String[] args) {11         12         WeatherData weatherData = new WeatherData();13         14         Observers temperatureObserver = new TemperatureBoard();15         Observers comitityObserver = new ComitityBoard();16         17         weatherData.registerObserver(temperatureObserver);18         weatherData.registerObserver(comitityObserver);19         20         //weatherData.removeObserver(comitityObserver);21         22         Random random = new Random();23         for(int i = 0 ; i < 100; i++){            24             if(random.nextInt(100) % 2 == 0){25                 weatherData.notifyObserver(random.nextInt(100));26             }27         }28     }29 30 }
驱动类

观察者模式是一对多的依赖关系,其中“一”对应主体,“多”对应观察者(们),也就是说当主体中的内容发生变化时,通过某种机制来通知观察者们,让观察者做一些应对的动作。观察者具有一个公共的接口,接口中定义了观察者公共的方法。所有具体的观察者都可以根据自身的特点来实现接口中的方法。主体中包含了的方法主要是:注册一个观察者,删除一个观察者,通知观察者。主体中存放了所有已注册的观察者的对象,当调用注册方法的时候,就往主体中添加一个新的观察者对象,当调用删除方法时,则将指定的观察者对象从主体中删除,当调用通知方法时,则用此用主体中保存的观察者对象来调用观察者的方法,从而实现当主体发生改变时,观察者作出相应应对的效果。实际上观察者模式往往给人的错觉是:观察者在实时的监听主体,一旦主体有变化,则作出相应应对。事实上观察者并没有去实时的监听主体,而是当主体发生改变的时候,主动的去“通知”观察者们作出相应动作(这里说通知,还不是很恰当,因为观察者每一次作出相应举动,都是主体主动利用存储的观察者对象来调用观察者的方法的,观察者始终处于一个被动的角色,主体利用一个共同的接口来更新观察者)。

补充:上面主要讲了主体(主题、可观察者)向观察者推送数据的方式,实际上也可以让观察者们主动去从主体那里去拿数据,只需要在每一个观察者中保存一份主体的对象,然后调用主体的方法来获得数据即可。但是一般认为被观察者向观察者“推”数据的方式比观察者们从可观察者那里“拿”数据的方式要好。

Java中内置了观察者模式(本人不推荐去使用,自己去实现更加灵活,能加深对于该模式的理解,况且该模式在思想上并不是很难。),Java程序设计语言在很多地方也采用了观察者模式,比较经典的就是在Swing中各种组件对于用户事件的监听。

  1 package java.util;  2   3 public class Observable {  4     private boolean changed = false;  5     private Vector obs;  6      7     /** Construct an Observable with zero Observers. */  8   9     public Observable() { 10     obs = new Vector(); 11     } 12  13     /** 14      * Adds an observer to the set of observers for this object, provided  15      * that it is not the same as some observer already in the set.  16      * The order in which notifications will be delivered to multiple  17      * observers is not specified. See the class comment. 18      * 19      * @param   o   an observer to be added. 20      * @throws NullPointerException   if the parameter o is null. 21      */ 22     public synchronized void addObserver(Observer o) { 23         if (o == null) 24             throw new NullPointerException(); 25     if (!obs.contains(o)) { 26         obs.addElement(o); 27     } 28     } 29  30     /** 31      * Deletes an observer from the set of observers of this object.  32      * Passing <CODE>null</CODE> to this method will have no effect. 33      * @param   o   the observer to be deleted. 34      */ 35     public synchronized void deleteObserver(Observer o) { 36         obs.removeElement(o); 37     } 38  39     /** 40      * If this object has changed, as indicated by the  41      * <code>hasChanged</code> method, then notify all of its observers  42      * and then call the <code>clearChanged</code> method to  43      * indicate that this object has no longer changed.  44      * <p> 45      * Each observer has its <code>update</code> method called with two 46      * arguments: this observable object and <code>null</code>. In other  47      * words, this method is equivalent to: 48      * <blockquote><tt> 49      * notifyObservers(null)</tt></blockquote> 50      * 51      * @see     java.util.Observable#clearChanged() 52      * @see     java.util.Observable#hasChanged() 53      * @see     java.util.Observer#update(java.util.Observable, java.lang.Object) 54      */ 55     public void notifyObservers() { 56     notifyObservers(null); 57     } 58  59     /** 60      * If this object has changed, as indicated by the  61      * <code>hasChanged</code> method, then notify all of its observers  62      * and then call the <code>clearChanged</code> method to indicate  63      * that this object has no longer changed.  64      * <p> 65      * Each observer has its <code>update</code> method called with two 66      * arguments: this observable object and the <code>arg</code> argument. 67      * 68      * @param   arg   any object. 69      * @see     java.util.Observable#clearChanged() 70      * @see     java.util.Observable#hasChanged() 71      * @see     java.util.Observer#update(java.util.Observable, java.lang.Object) 72      */ 73     public void notifyObservers(Object arg) { 74     /* 75          * a temporary array buffer, used as a snapshot of the state of 76          * current Observers. 77          */ 78         Object[] arrLocal; 79  80     synchronized (this) { 81         /* We don't want the Observer doing callbacks into 82          * arbitrary code while holding its own Monitor. 83          * The code where we extract each Observable from  84          * the Vector and store the state of the Observer 85          * needs synchronization, but notifying observers 86          * does not (should not).  The worst result of any  87          * potential race-condition here is that: 88          * 1) a newly-added Observer will miss a 89          *   notification in progress 90          * 2) a recently unregistered Observer will be 91          *   wrongly notified when it doesn't care 92          */ 93         if (!changed) 94                 return; 95             arrLocal = obs.toArray(); 96             clearChanged(); 97         } 98  99         for (int i = arrLocal.length-1; i>=0; i--)100             ((Observer)arrLocal[i]).update(this, arg);101     }102 103     /**104      * Clears the observer list so that this object no longer has any observers.105      */106     public synchronized void deleteObservers() {107     obs.removeAllElements();108     }109 110     /**111      * Marks this <tt>Observable</tt> object as having been changed; the 112      * <tt>hasChanged</tt> method will now return <tt>true</tt>.113      */114     protected synchronized void setChanged() {115     changed = true;116     }117 118     /**119      * Indicates that this object has no longer changed, or that it has 120      * already notified all of its observers of its most recent change, 121      * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>. 122      * This method is called automatically by the 123      * <code>notifyObservers</code> methods. 124      *125      * @see     java.util.Observable#notifyObservers()126      * @see     java.util.Observable#notifyObservers(java.lang.Object)127      */128     protected synchronized void clearChanged() {129     changed = false;130     }131 132     /**133      * Tests if this object has changed. 134      *135      * @return  <code>true</code> if and only if the <code>setChanged</code> 136      *          method has been called more recently than the 137      *          <code>clearChanged</code> method on this object; 138      *          <code>false</code> otherwise.139      * @see     java.util.Observable#clearChanged()140      * @see     java.util.Observable#setChanged()141      */142     public synchronized boolean hasChanged() {143     return changed;144     }145 146     /**147      * Returns the number of observers of this <tt>Observable</tt> object.148      *149      * @return  the number of observers of this object.150      */151     public synchronized int countObservers() {152     return obs.size();153     }154 }
java.util.Observable源码
 1 package java.util; 2  3 public interface Observer { 4     /** 5      * This method is called whenever the observed object is changed. An 6      * application calls an <tt>Observable</tt> object's 7      * <code>notifyObservers</code> method to have all the object's 8      * observers notified of the change. 9      *10      * @param   o     the observable object.11      * @param   arg   an argument passed to the <code>notifyObservers</code>12      *                 method.13      */14     void update(Observable o, Object arg);15 }
java.util.Observer源码

 

 

0 0
原创粉丝点击