Question
I'm having trouble understanding the following UML-diagram of the Observer pattern from the "Elements of Reusable Object-Oriented Software". Could anyone explain me why my Java implementation is wrong and what I have to change to implement it correctly?
UML-Diagram
Attempted (but wrong) implementation
public interface Subject {
public static final List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer o);
public void detach(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private String subjectState;
@Override
public void attach(Observer o) {
observers.add(o);
}
@Override
public void detach(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer o : observers) {
o.update();
}
}
public String getState() {
return subjectState;
}
public void setState() {
subjectState += "x";
}
}
public class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public String observerState;
@Override
public void update() {
observerState = subject.getState();
}
}
One problem is that you have a static list of observers in Subject
so all subjects share the same observers. However, the pattern requires that each individual subject has its own observers so put the list into ConcreteSubject
and make it an instance field.
Another problem is that your ConcreteObserver
has a field of type ConcreteSubject
. It should, however, not know about the concrete implementation of Subject
so the field should only have the type Subject
.
Edit : Actually the UML diagram requires the concrete observer to know about the concrete subject in order to be able to call getState()
so the above paragraph is not true in your case - this should not be a problem here.
However, in reality I would actually have another interface that extends Subject
and hides the implementation of ConcreteSubject
from the observer.
Edit 2 :
As has been suggested you could also use an abstract class to handle the observers of a subject. That could be a class in between Subject
and ConcreteSubject
or even Subject
itself but since Java doesn't support multiple inheritance I'd often use some other approach and make Subject
just an interface.
The easiest implementation would then be to have ConcreteSubject
maintain the list of observers but in a real world application you'd not want to have developers do that or rely on them implementing it correctly.
Instead you could use a central registry that maintains the list of observers for each subject and which the subject uses to inform its observers. Many dependency injection frameworks out there operate in a way like that, ie whenever a "subject" changes they will inform its observers about that event.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.