If it were me, I would keep the generics a bit simpler, and would implement the code much closer to the original Observer, except adding the generics.
I have used your code as a template, but then restructured, and rewritten parts, to be:
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Supplier;
/**
* like java.util.Observable, But uses generics to avoid need for a cast.
*
* For any un-documented variable, parameter or method, see java.util.Observable
*/
public class Observable<T> {
public interface Observer<U> {
public void update(Observable<? extends U> observer, U arg);
}
private boolean changed = false;
private final Collection<Observer<? super T>> observers;
public Observable() {
this(ArrayList::new);
}
public Observable(Supplier<Collection<Observer<? super T>>> supplier) {
observers = supplier.get();
}
public void addObserver(final Observer<? super T> observer) {
synchronized (observers) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
}
public void removeObserver(final Observer<? super T> observer) {
synchronized (observers) {
observers.remove(observer);
}
}
public void clearObservers() {
synchronized (observers) {
this.observers.clear();
}
}
public void setChanged() {
synchronized (observers) {
this.changed = true;
}
}
public void clearChanged() {
synchronized (observers) {
this.changed = false;
}
}
public boolean hasChanged() {
synchronized (observers) {
return this.changed;
}
}
public int countObservers() {
synchronized (observers) {
return observers.size();
}
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(final T value) {
ArrayList<Observer<? super T>> toNotify = null;
synchronized(observers) {
if (!changed) {
return;
}
toNotify = new ArrayList<>(observers);
changed = false;
}
for (Observer<? super T> observer : toNotify) {
observer.update(this, value);
}
}
}
Note that, apart from the generics, the signatures are the same as the existing Observable.
Additionally, the synchroization uses an internal instance, and I use Java8 suppiers to have a constructor giving a collection. That way you can get a safe instance for the synchronization.
The original Observer is not synchronized, and, this one does things a little differently in the notify method, because it does the notification after doing the changed=false
change. THe JavaDoc for the original Observable indicates that the change should only be reset after the notifications....