Java Tutorial/Design Pattern/Observable and Observer
Содержание
An object may be observed by two or more observers.
<source lang="java">
import java.util.Observable; import java.util.Observer; class Watcher1 implements Observer {
public void update(Observable obj, Object arg) { System.out.println("update() called, count is " + ((Integer) arg).intValue()); }
} class Watcher2 implements Observer {
public void update(Observable obj, Object arg) { if (((Integer) arg).intValue() == 0) System.out.println("Done"); }
} class BeingWatched extends Observable {
void counter(int period) { for (; period >= 0; period--) { setChanged(); notifyObservers(new Integer(period)); try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println("Sleep interrupted"); } } }
} class MainClass {
public static void main(String args[]) { BeingWatched observed = new BeingWatched(); Watcher1 observing1 = new Watcher1(); Watcher2 observing2 = new Watcher2(); observed.addObserver(observing1); observed.addObserver(observing2); observed.counter(10); }
}</source>
Demonstrate the Observable class and the Observer interface.
<source lang="java">
import java.util.Observable; import java.util.Observer; class Watcher implements Observer {
public void update(Observable obj, Object arg) { System.out.println("update() called, count is " + ((Integer) arg).intValue()); }
} class BeingWatched extends Observable {
void counter(int period) { for (; period >= 0; period--) { setChanged(); notifyObservers(new Integer(period)); try { Thread.sleep(100); } catch (InterruptedException e) { System.out.println("Sleep interrupted"); } } }
} class ObserverDemo {
public static void main(String args[]) { BeingWatched observed = new BeingWatched(); Watcher observing = new Watcher(); observed.addObserver(observing); observed.counter(10); }
}</source>
Demonstration of "observer" pattern.
<source lang="java">
import java.util.Observable; import java.util.Observer; class Library {
private boolean isOpen; private OpenNotifier oNotify = new OpenNotifier(); private CloseNotifier cNotify = new CloseNotifier(); public Library() { isOpen = false; } public void open() { // Opens its petals isOpen = true; oNotify.notifyObservers(); cNotify.open(); } public void close() { // Closes its petals isOpen = false; cNotify.notifyObservers(); oNotify.close(); } public Observable opening() { return oNotify; } public Observable closing() { return cNotify; } private class OpenNotifier extends Observable { private boolean alreadyOpen = false; public void notifyObservers() { if (isOpen && !alreadyOpen) { setChanged(); super.notifyObservers(); alreadyOpen = true; } } public void close() { alreadyOpen = false; } } private class CloseNotifier extends Observable { private boolean alreadyClosed = false; public void notifyObservers() { if (!isOpen && !alreadyClosed) { setChanged(); super.notifyObservers(); alreadyClosed = true; } } public void open() { alreadyClosed = false; } }
} class Student {
private String name; private OpenObserver openObsrv = new OpenObserver(); private CloseObserver closeObsrv = new CloseObserver(); public Student(String nm) { name = nm; } private class OpenObserver implements Observer { public void update(Observable ob, Object a) { System.out.println("Student " + name + ""s study time!"); } } private class CloseObserver implements Observer { public void update(Observable ob, Object a) { System.out.println("Student " + name + ""s bed time!"); } } public Observer openObserver() { return openObsrv; } public Observer closeObserver() { return closeObsrv; }
} class Professor {
private String name; private OpenObserver openObsrv = new OpenObserver(); private CloseObserver closeObsrv = new CloseObserver(); public Professor(String nm) { name = nm; } private class OpenObserver implements Observer { public void update(Observable ob, Object a) { System.out.println("Professor " + name + ""s research time!"); } } private class CloseObserver implements Observer { public void update(Observable ob, Object a) { System.out.println("Professor " + name + ""s bed time!"); } } public Observer openObserver() { return openObsrv; } public Observer closeObserver() { return closeObsrv; }
} public class ObservedFlower {
public static void main(String args[]) { Library f = new Library(); Student ba = new Student("A"), bb = new Student("B"); Professor ha = new Professor("A"), hb = new Professor("B"); f.opening().addObserver(ha.openObserver()); f.opening().addObserver(hb.openObserver()); f.opening().addObserver(ba.openObserver()); f.opening().addObserver(bb.openObserver()); f.closing().addObserver(ha.closeObserver()); f.closing().addObserver(hb.closeObserver()); f.closing().addObserver(ba.closeObserver()); f.closing().addObserver(bb.closeObserver()); f.opening().deleteObserver(hb.openObserver()); f.open(); f.open(); f.closing().deleteObserver(ba.closeObserver()); f.close(); f.close(); f.opening().deleteObservers(); f.open(); f.close(); }
}</source>
Observable and Observer Objects
<source lang="java">
import java.util.Observable; import java.util.Observer; class MyObservable extends Observable {
public void drinkPotion() { name = "jexp "; setChanged(); notifyObservers(); } public String getName() { return name; } private String name = "jexp";
} class Person implements Observer {
public Person(String name, String says) { this.name = name; this.says = says; } public void update(Observable thing, Object o) { System.out.println("It"s " + ((MyObservable) thing).getName() + "\n" + name + ": " + says); } private String name; private String says;
} public class MainClass {
public static void main(String[] args) { MyObservable man = new MyObservable(); Observer[] crowd = { new Person("A", "a"), new Person("B", "b"), new Person("C", "c"), new Person("D", "d"), new Person("E", "e") }; for (Observer observer : crowd) { man.addObserver(observer); } man.drinkPotion(); }
}</source>
It"s jexp E: e It"s jexp D: d It"s jexp C: c It"s jexp B: b It"s jexp A: a">
Timeout Observer
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
import java.util.Enumeration; import java.util.Vector; /**
* Generalization of ExecuteWatchdog
*
* @see org.apache.rumons.exec.ExecuteWatchdog
*/
public class Watchdog implements Runnable {
private Vector observers = new Vector(1); private final long timeout; private boolean stopped = false; public Watchdog(final long timeout) { if (timeout < 1) { throw new IllegalArgumentException("timeout must not be less than 1."); } this.timeout = timeout; } public void addTimeoutObserver(final TimeoutObserver to) { observers.addElement(to); } public void removeTimeoutObserver(final TimeoutObserver to) { observers.removeElement(to); } protected final void fireTimeoutOccured() { Enumeration e = observers.elements(); while (e.hasMoreElements()) { ((TimeoutObserver) e.nextElement()).timeoutOccured(this); } } public synchronized void start() { stopped = false; Thread t = new Thread(this, "WATCHDOG"); t.setDaemon(true); t.start(); } public synchronized void stop() { stopped = true; notifyAll(); } public synchronized void run() { final long until = System.currentTimeMillis() + timeout; long now; while (!stopped && until > (now = System.currentTimeMillis())) { try { wait(until - now); } catch (InterruptedException e) { } } if (!stopped) { fireTimeoutOccured(); } }
} /**
* Interface for classes that want to be notified by Watchdog. * * @see org.apache.rumons.exec.Watchdog */
interface TimeoutObserver {
/** * Called when the watchdow times out. * * @param w * the watchdog that timed out. */ void timeoutOccured(Watchdog w);
}</source>
Watch What is Going On with the Observer Patterns
<source lang="java">
import java.util.Vector; public class TestObserver {
public static void main(String args[]) { Database database = new Database(); Archiver archiver = new Archiver(); Client client = new Client(); Boss boss = new Boss(); database.registerObserver(archiver); database.registerObserver(client); database.registerObserver(boss); database.editRecord("delete", "record 1"); }
} interface Observer {
public void update(String operation, String record);
} interface Subject {
public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers();
} class Database implements Subject {
private Vector<Observer> observers; private String operation; private String record; public Database() { observers = new Vector<Observer>(); } public void registerObserver(Observer o) { observers.add(o); } public void removeObserver(Observer o) { observers.remove(o); } public void notifyObservers() { for (int loopIndex = 0; loopIndex < observers.size(); loopIndex++) { Observer observer = (Observer) observers.get(loopIndex); observer.update(operation, record); } } public void editRecord(String operation, String record) { this.operation = operation; this.record = record; notifyObservers(); }
} class Client implements Observer {
public Client() { } public void update(String operation, String record) { System.out.println("The client says a " + operation + " operation was performed on " + record); }
} class Boss implements Observer {
public Boss() { } public void update(String operation, String record) { System.out.println("The boss says a " + operation + " operation was performed on " + record); }
} class Archiver implements Observer {
public Archiver() { } public void update(String operation, String record) { System.out .println("The archiver says a " + operation + " operation was performed on " + record); }
}</source>