Observer-Pattern

Status
Nicht offen für weitere Antworten.
Hallo,
ich möchte gerne das Observer Pattern implementieren, habe aber das Problem, dass meine 'Observable-Klasse'
schon von einer anderen Klase erbt, also Observable nicht mehr erweitern kann.
Ich hatte nun die Idee, die Funktionalität über Delegation zu erhalten, dabei aber festgestellt, dass die setChanged-Methode protected ist.
Was gibt es nun für Möglichkeiten? Muss ich das Muster einfach selbst nachbilden oder gibt es noch eine andere Möglichkeit?
Danke für eine Antwort.
 
eine Zwischenlösung wäre evtl., die Klasse zu überschreiben und fehlende public-Methoden anzubieten, die dann intern die protected-Methoden aufrufen,

oder selber komplett nachbauen/ kopieren, entweder in deiner Klasse oder in einer anderen Klasse, die delegiert wird,

ein typisches Problem bei der Beschränkung auf Einfach-Vererbung,
-----
falls du den Quellcode nicht hast:

Code:
public class Observable {
    private boolean changed = false;
    private Vector obs;
   
    /** Construct an Observable with zero Observers. */

    public Observable() {
	obs = new Vector();
    }

    /**
     * Adds an observer to the set of observers for this object, provided 
     * that it is not the same as some observer already in the set. 
     * The order in which notifications will be delivered to multiple 
     * observers is not specified. See the class comment.
     *
     * @param   o   an observer to be added.
     * @throws NullPointerException   if the parameter o is null.
     */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
	if (!obs.contains(o)) {
	    obs.addElement(o);
	}
    }

    /**
     * Deletes an observer from the set of observers of this object. 
     * Passing <CODE>null</CODE> to this method will have no effect.
     * @param   o   the observer to be deleted.
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /**
     * If this object has changed, as indicated by the 
     * <code>hasChanged</code> method, then notify all of its observers 
     * and then call the <code>clearChanged</code> method to 
     * indicate that this object has no longer changed. 
     * 


     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and <code>null</code>. In other 
     * words, this method is equivalent to:
     * <blockquote><tt>
     * notifyObservers(null)</tt></blockquote>
     *
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers() {
	notifyObservers(null);
    }

    /**
     * If this object has changed, as indicated by the 
     * <code>hasChanged</code> method, then notify all of its observers 
     * and then call the <code>clearChanged</code> method to indicate 
     * that this object has no longer changed. 
     * 


     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and the <code>arg</code> argument.
     *
     * @param   arg   any object.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers(Object arg) {
	/*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

	synchronized (this) {
	    /* We don't want the Observer doing callbacks into
	     * arbitrary code while holding its own Monitor.
	     * The code where we extract each Observable from 
	     * the Vector and store the state of the Observer
	     * needs synchronization, but notifying observers
	     * does not (should not).  The worst result of any 
	     * potential race-condition here is that:
	     * 1) a newly-added Observer will miss a
	     *   notification in progress
	     * 2) a recently unregistered Observer will be
	     *   wrongly notified when it doesn't care
	     */
	    if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /**
     * Clears the observer list so that this object no longer has any observers.
     */
    public synchronized void deleteObservers() {
	obs.removeAllElements();
    }

    /**
     * Marks this <tt>Observable</tt> object as having been changed; the 
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
     */
    protected synchronized void setChanged() {
	changed = true;
    }

    /**
     * Indicates that this object has no longer changed, or that it has 
     * already notified all of its observers of its most recent change, 
     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>. 
     * This method is called automatically by the 
     * <code>notifyObservers</code> methods. 
     *
     * @see     java.util.Observable#notifyObservers()
     * @see     java.util.Observable#notifyObservers(java.lang.Object)
     */
    protected synchronized void clearChanged() {
	changed = false;
    }

    /**
     * Tests if this object has changed. 
     *
     * @return  <code>true</code> if and only if the <code>setChanged</code> 
     *          method has been called more recently than the 
     *          <code>clearChanged</code> method on this object; 
     *          <code>false</code> otherwise.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#setChanged()
     */
    public synchronized boolean hasChanged() {
	return changed;
    }

    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     *
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
	return obs.size();
    }
}
 
Danke,
hab mir schon gedacht, dass es keine schöne saubere Lösung dafür gibt.
Da ich nicht die ganze Funktionalität der Observable Klasse brauche, werde ich mir das nötige rauskopieren.
Ich hab aber noch eine andere Frage.
Meine beobachtbare Klasse ist eine erweiterte 'LinkedList'.
Mein Beobachter soll immer informiert werden, wenn sich an der Liste irgenetwas verändert hat.
Muss ich nun alle 'add' , 'set' und 'remove'-Methoden der Linked List mit dem Codefragment
Code:
setChanged(true); 
notifyObservers();
überschreiben?
Oder gibt es irgendeine Möglichkeit, dass das meine erweiterte LinkedList selbst merkt, dass sich ihr Zustand verändert hat und ich ihr mit einem einfachen einzelnen Codestück mitteilen kann, dass sie dann immer alle Beobachter benachrichtigen soll. Also in der Art, wie es bei den Listenern funktioniert.
 
wenn es schon ein Listener-System gäbe, wie z.B. beim DefaultTableModel jede Methode fireTableDataChanged() oder ähnliches aufruft,
dann könntest du einen Standard-Listener an das eigene Objekt ranhängen und damit auf Änderungen reagieren um deinen persönlichen Listener zu aktivieren,

klingt doppelt gemoppelt, kommt aber wohl eh nicht in Frage, da eine LinkedList von Natur aus nichts derartiges unterstützt

wenn man ganz tief in die Implementierung von LinkedList reinginge,
hätte man noch den Vorteil, nur in wenigen zentralen (private) Methoden die Informierung vornehmen zu müssen,
so bleibt dir aber wohl nur das flächendeckende Überschreiben,

10x zwei Codezeilen einzufügen ist aber schon zuviel Aufwand,
wenn es immer
> setChanged(true);
> notifyObservers();
sein muss, dann definiere dir eine Hilfsmethode setChangedAndNotify();
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben