I'm implementing observer pattern in the following way:
interface Layer{
void adjustString(Set<String> strings);
}
interface NotifiableLayer extends Layer{
void layerAdjusted(Layer layer);
}
abstract class ObservableLayer implements Layer{
Set<NotifiableLayer> observers = new HashSet<>();
void addObserver(NotifiableLayer layer){
observers.add(layer);
}
void removeObserver(NotifiableLayer layer){
observers.remove(layer);
}
void notifyObservers(){
observers.forEach(l -> l.layerAdjusted(this));
}
}
class MyLayer extends ObservableLayer{
@Override
public void adjustString(Set<String> strings) {
this.notifyObservers(); //can this be auto?
}
}
And this works of course, but whoever is implementing ObservableLayer needs to remember to call this.notifyObservers() in the adjustString method. This is not that of a big deal, but I wanted to see if there is a way to completely hide this.
So far, I only have this idea (using template method):
abstract class ObservableLayer implements Layer{
//...methods removed for simplicity
@Override
public void adjustString(Set<String> strings) {
this.doAdjustString(strings);
this.notifyObservers(); //<---- here is auto
}
abstract void doAdjustString(Set<String> strings);
}
class MyLayer extends ObservableLayer{
@Override
public void doAdjustString(Set<String> strings) {
//now notification is in base adjustString
}
}
but here I don't like that method name changed to doAdjustString, and it is not anymore uniform between other layer implementations (layers that directly implement Layer interface).
Is there any easy way to have this functionallity, but to keep public void adjustString(Set<String> strings) signature in MyLayer class?
One way would be to use a Decorator instance that holds an
ObservableLayerinstance and delegates to it.This assumes that calling code is working using references to
Layerinstead ofObservableLayer.If calling code has to work using references to
ObservableLayerthen maybe it is better to refactorObservableLayerto be an interface having the methods to register listeners, remove them and notify them. This interface also extends theLayerinterface.The abstract class
ObservableLayerchanges to implementIObservableLayerinstead ofLayerdirectly. This class remains public to support application classes to define variations of observable layers.Next an internal decorator for observable layers can be defined as shown below.
Please note how the notification is done in this case.
Now instances of
IObservableLayercan be created asFactory methods will be helpful here as they can be defined to handle creation of various application-level observable layer classes so that the instances can be created consistently that return an
IObservableLayerwhich is decorated. That will free up developers from knowing how to use the decorator and allow the decorator to be an internal utility.