dimanche 8 novembre 2020

Observer with full transparency

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?

Aucun commentaire:

Enregistrer un commentaire