1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.util; 19 20 /** 21 * Observable is used to notify a group of Observer objects when a change 22 * occurs. On creation, the set of observers is empty. After a change occurred, 23 * the application can call the {@link #notifyObservers()} method. This will 24 * cause the invocation of the {@code update()} method of all registered 25 * Observers. The order of invocation is not specified. This implementation will 26 * call the Observers in the order they registered. Subclasses are completely 27 * free in what order they call the update methods. 28 * 29 * @see Observer 30 */ 31 public class Observable { 32 33 List<Observer> observers = new ArrayList<Observer>(); 34 35 boolean changed = false; 36 37 /** 38 * Constructs a new {@code Observable} object. 39 */ 40 public Observable() { 41 } 42 43 /** 44 * Adds the specified observer to the list of observers. If it is already 45 * registered, it is not added a second time. 46 * 47 * @param observer 48 * the Observer to add. 49 */ 50 public void addObserver(Observer observer) { 51 if (observer == null) { 52 throw new NullPointerException(); 53 } 54 synchronized (this) { 55 if (!observers.contains(observer)) 56 observers.add(observer); 57 } 58 } 59 60 /** 61 * Clears the changed flag for this {@code Observable}. After calling 62 * {@code clearChanged()}, {@code hasChanged()} will return {@code false}. 63 */ 64 protected void clearChanged() { 65 changed = false; 66 } 67 68 /** 69 * Returns the number of observers registered to this {@code Observable}. 70 * 71 * @return the number of observers. 72 */ 73 public int countObservers() { 74 return observers.size(); 75 } 76 77 /** 78 * Removes the specified observer from the list of observers. Passing null 79 * won't do anything. 80 * 81 * @param observer 82 * the observer to remove. 83 */ 84 public synchronized void deleteObserver(Observer observer) { 85 observers.remove(observer); 86 } 87 88 /** 89 * Removes all observers from the list of observers. 90 */ 91 public synchronized void deleteObservers() { 92 observers.clear(); 93 } 94 95 /** 96 * Returns the changed flag for this {@code Observable}. 97 * 98 * @return {@code true} when the changed flag for this {@code Observable} is 99 * set, {@code false} otherwise. 100 */ 101 public boolean hasChanged() { 102 return changed; 103 } 104 105 /** 106 * If {@code hasChanged()} returns {@code true}, calls the {@code update()} 107 * method for every observer in the list of observers using null as the 108 * argument. Afterwards, calls {@code clearChanged()}. 109 * <p> 110 * Equivalent to calling {@code notifyObservers(null)}. 111 */ 112 public void notifyObservers() { 113 notifyObservers(null); 114 } 115 116 /** 117 * If {@code hasChanged()} returns {@code true}, calls the {@code update()} 118 * method for every Observer in the list of observers using the specified 119 * argument. Afterwards calls {@code clearChanged()}. 120 * 121 * @param data 122 * the argument passed to {@code update()}. 123 */ 124 @SuppressWarnings("unchecked") 125 public void notifyObservers(Object data) { 126 int size = 0; 127 Observer[] arrays = null; 128 synchronized (this) { 129 if (hasChanged()) { 130 clearChanged(); 131 size = observers.size(); 132 arrays = new Observer[size]; 133 observers.toArray(arrays); 134 } 135 } 136 if (arrays != null) { 137 for (Observer observer : arrays) { 138 observer.update(this, data); 139 } 140 } 141 } 142 143 /** 144 * Sets the changed flag for this {@code Observable}. After calling 145 * {@code setChanged()}, {@code hasChanged()} will return {@code true}. 146 */ 147 protected void setChanged() { 148 changed = true; 149 } 150 } 151