mercredi 9 juin 2021

Observer pattern in python - automatically unsubscribe at the end of observer's lifetime

I'm currently learning design patterns and was trying to implement Observer pattern in python

Here is the snippet from my implementation (not complete, but enough for explaining by doubt) -

class Observer(ABC):
    def __init__(self):
        self.subjects_ : list[Observable] = []

    def add_subject(self, sub: Type['Observable']):
        self.subjects_.append(sub)
        sub.add_observer(self)
        return

    @abstractmethod
    def notify(self, sub: Type['Observable']):
        pass

    def __del__(self):           # ------ here is the focus of my question
        for sub in self.subjects_:
            sub.remove_observer(self)


class Observable(ABC):
    def __init__(self):
        self.observers_ = []

    def add_observer(self, obs: Observer):
        self.observers_.append(obs)
        return 

    def remove_observer(self, obs: Observer):
        ind = self.observers_.index(obs)
        del self.observers_[ind]
        logging.info('Observer removed')

Here is the driver code -

class WeatherStation(Observable):
    pass # skipping the class defn to keep the question short

class WeatherPhoneApp(Observer):
    # skipping the class defn to keep the question short
    def notify(self, ws: WeatherStation):
        temperature = ws.get_temperature()
        print("Hi {}, the temperature today is - {}".format(self.user_name_, temperature))


if __name__ == '__main__':
    ws = WeatherStation("Scranton")

    my_phone_ws_app = WeatherPhoneApp("Micheal", ws)
    friends_phone_ws_app = WeatherPhoneApp("Dwight", ws)

    ws.update_temperature(28)
    # output here - 
    # Hi Micheal, the temperature today is - 28
    # Hi Dwight, the temperature today is - 28

    del friends_phone_ws_app   

    ws.update_temperature(25) 
    # output here - 
    # Hi Micheal, the temperature today is - 25
    # Hi Dwight, the temperature today is - 25            (I wasn't expecting this line)

Notice that after friends_phone_ws_app out of scope, updates are still printed.

I assume that the call to del(friends_phone_ws_app) doesn't delete the object since there are 2 references (via friends_phone_ws_app and via Observable.observers_) to the object and __del__ will be called when all references are gone.

To summarise, what is the best way to implement automatic unsubscribe when the observer object goes out of scope?

Please comment if my question is unclear/incomplete, I can provide more details

Aucun commentaire:

Enregistrer un commentaire