设计模式二—“观察者模式”
观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。(出版者+订阅者=观察者模式)
point1:一对多关系
point2:松耦合
为什么要有观察者模式?
观察者模式适合于这样一种情况,现在有某一类主题信息,对于它有很多的观察者,观察者关注主题的信息,同时观察者希望主题对象可以再事实更新的时候同步把更新的信息“推”送到观察者哪里,当然,为了更灵活,观察者也希望可以主动的“拉取”更新的信息,因为对于种类繁多的观察者,并不是所有的人都需要更新全部的信息,因为很有可能,更新的一大部分信息里,某些观察者是不关注的。
用类图定义观察者模式
使用Eclipse的一个UML插件(AmaterasUML)自动生成我们需要的类图。
这样我们就很清楚的认识了这种模式一个主题被多个订阅者订阅。同时,也是针对接口进行编程的体现。
观察者模式!
Java内置的观察者模式!并灵活的实现了我们所期待的需求。
以java源码中的Observable,和Observer
打开java.util.Observable(java内置可观察者)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 26 package java.util; 27 28 /** 29 * This class represents an observable object, or "data" 30 * in the model-view paradigm. It can be subclassed to represent an 31 * object that the application wants to have observed. 32 * <p> 33 * An observable object can have one or more observers. An observer 34 * may be any object that implements interface <tt>Observer</tt>. After an 35 * observable instance changes, an application calling the 36 * <code>Observable</code>'s <code>notifyObservers</code> method 37 * causes all of its observers to be notified of the change by a call 38 * to their <code>update</code> method. 39 * <p> 40 * The order in which notifications will be delivered is unspecified. 41 * The default implementation provided in the Observable class will 42 * notify Observers in the order in which they registered interest, but 43 * subclasses may change this order, use no guaranteed order, deliver 44 * notifications on separate threads, or may guarantee that their 45 * subclass follows this order, as they choose. 46 * <p> 47 * Note that this notification mechanism is has nothing to do with threads 48 * and is completely separate from the <tt>wait</tt> and <tt>notify</tt> 49 * mechanism of class <tt>Object</tt>. 50 * <p> 51 * When an observable object is newly created, its set of observers is 52 * empty. Two observers are considered the same if and only if the 53 * <tt>equals</tt> method returns true for them. 54 * 55 * @author Chris Warth 56 * @see java.util.Observable#notifyObservers() 57 * @see java.util.Observable#notifyObservers(java.lang.Object) 58 * @see java.util.Observer 59 * @see java.util.Observer#update(java.util.Observable, java.lang.Object) 60 * @since JDK1.0 61 */ 62 public class Observable { 63 private boolean changed = false; 64 private Vector obs; 65 66 /** Construct an Observable with zero Observers. */ 67 68 public Observable() { 69 obs = new Vector(); 70 } 71 72 /** 73 * Adds an observer to the set of observers for this object, provided 74 * that it is not the same as some observer already in the set. 75 * The order in which notifications will be delivered to multiple 76 * observers is not specified. See the class comment. 77 * 78 * @param o an observer to be added. 79 * @throws NullPointerException if the parameter o is null. 80 */ 81 public synchronized void addObserver(Observer o) { 82 if (o == null) 83 throw new NullPointerException(); 84 if (!obs.contains(o)) { 85 obs.addElement(o); 86 } 87 } 88 89 /** 90 * Deletes an observer from the set of observers of this object. 91 * Passing <CODE>null</CODE> to this method will have no effect. 92 * @param o the observer to be deleted. 93 */ 94 public synchronized void deleteObserver(Observer o) { 95 obs.removeElement(o); 96 } 97 98 /** 99 * If this object has changed, as indicated by the 100 * <code>hasChanged</code> method, then notify all of its observers 101 * and then call the <code>clearChanged</code> method to 102 * indicate that this object has no longer changed. 103 * <p> 104 * Each observer has its <code>update</code> method called with two 105 * arguments: this observable object and <code>null</code>. In other 106 * words, this method is equivalent to: 107 * <blockquote><tt> 108 * notifyObservers(null)</tt></blockquote> 109 * 110 * @see java.util.Observable#clearChanged() 111 * @see java.util.Observable#hasChanged() 112 * @see java.util.Observer#update(java.util.Observable, java.lang.Object) 113 */ 114 public void notifyObservers() { 115 notifyObservers(null); 116 } 117 118 /** 119 * If this object has changed, as indicated by the 120 * <code>hasChanged</code> method, then notify all of its observers 121 * and then call the <code>clearChanged</code> method to indicate 122 * that this object has no longer changed. 123 * <p> 124 * Each observer has its <code>update</code> method called with two 125 * arguments: this observable object and the <code>arg</code> argument. 126 * 127 * @param arg any object. 128 * @see java.util.Observable#clearChanged() 129 * @see java.util.Observable#hasChanged() 130 * @see java.util.Observer#update(java.util.Observable, java.lang.Object) 131 */ 132 public void notifyObservers(Object arg) { 133 /* 134 * a temporary array buffer, used as a snapshot of the state of 135 * current Observers. 136 */ 137 Object[] arrLocal; 138 139 synchronized (this) { 140 /* We don't want the Observer doing callbacks into 141 * arbitrary code while holding its own Monitor. 142 * The code where we extract each Observable from 143 * the Vector and store the state of the Observer 144 * needs synchronization, but notifying observers 145 * does not (should not). The worst result of any 146 * potential race-condition here is that: 147 * 1) a newly-added Observer will miss a 148 * notification in progress 149 * 2) a recently unregistered Observer will be 150 * wrongly notified when it doesn't care 151 */ 152 if (!changed) 153 return; 154 arrLocal = obs.toArray(); 155 clearChanged(); 156 } 157 158 for (int i = arrLocal.length-1; i>=0; i--) 159 ((Observer)arrLocal[i]).update(this, arg); 160 } 161 162 /** 163 * Clears the observer list so that this object no longer has any observers. 164 */ 165 public synchronized void deleteObservers() { 166 obs.removeAllElements(); 167 } 168 169 /** 170 * Marks this <tt>Observable</tt> object as having been changed; the 171 * <tt>hasChanged</tt> method will now return <tt>true</tt>. 172 */ 173 protected synchronized void setChanged() { 174 changed = true; 175 } 176 177 /** 178 * Indicates that this object has no longer changed, or that it has 179 * already notified all of its observers of its most recent change, 180 * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>. 181 * This method is called automatically by the 182 * <code>notifyObservers</code> methods. 183 * 184 * @see java.util.Observable#notifyObservers() 185 * @see java.util.Observable#notifyObservers(java.lang.Object) 186 */ 187 protected synchronized void clearChanged() { 188 changed = false; 189 } 190 191 /** 192 * Tests if this object has changed. 193 * 194 * @return <code>true</code> if and only if the <code>setChanged</code> 195 * method has been called more recently than the 196 * <code>clearChanged</code> method on this object; 197 * <code>false</code> otherwise. 198 * @see java.util.Observable#clearChanged() 199 * @see java.util.Observable#setChanged() 200 */ 201 public synchronized boolean hasChanged() { 202 return changed; 203 } 204 205 /** 206 * Returns the number of observers of this <tt>Observable</tt> object. 207 * 208 * @return the number of observers of this object. 209 */ 210 public synchronized int countObservers() { 211 return obs.size(); 212 } 213 }
打开Observer(java内置观察者)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 package java.util; 26 27 /** 28 * A class can implement the <code>Observer</code> interface when it 29 * wants to be informed of changes in observable objects. 30 * 31 * @author Chris Warth 32 * @see java.util.Observable 33 * @since JDK1.0 34 */ 35 public interface Observer { 36 /** 37 * This method is called whenever the observed object is changed. An 38 * application calls an <tt>Observable</tt> object's 39 * <code>notifyObservers</code> method to have all the object's 40 * observers notified of the change. 41 * 42 * @param o the observable object. 43 * @param arg an argument passed to the <code>notifyObservers</code> 44 * method. 45 */ 46 void update(Observable o, Object arg); 47 }
如何应用java的内置观察者模式进行编程!
主题subject扩展Observable类,调用addObserver()和deleteObserver()方法添加删除观察者,通过setChanged()通知状态改变,并调用notifyObservers或者notifyObservers(Object arg)通知所有的观察者,第二个函数的参数arg可以封装传递的数据对象,通知结束后要将Changed状态设回false。
观察者扩展Observer类,调用update(Observable o,Object arg)实现数据的更新。后一个参数也就是传入notifyObservers的参数。
SIDE EFFECT:
因为在参考Observable 通知对象的实现的时候,次序是按照内部实现定义好的,不好进行控制。多以在某些场合下,我们还是需要参照这样一种实现方式,来重新设计我们的代码。又因为Observable是一个类而不是一个接口,继承限制了它的复用。所以对于java提供的这种内置观察者模式,我们应该谨慎选用,一旦发现有可能出现问题,还是自己去实现一套观察者模式比较灵活。