Passed
Push — dev ( 4bfa05...67478a )
by Konstantinos
01:31
created

SubjectInterface.notify()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
from abc import ABC, abstractmethod
2
from typing import List
3
4
__all__ = ['Subject', 'Observer']
5
6
7
class ObserverInterface(ABC):
8
    """The Observer interface declares the update method, used by subjects. Whenever an 'event' happens the update
9
    callback executes."""
10
    @abstractmethod
11
    def update(self, *args, **kwargs) -> None:
12
        """Receive update from subject."""
13
        raise NotImplementedError
14
15
16
class SubjectInterface(ABC):
17
    """The Subject interface declares a set of methods for managing subscribers.
18
    Use it to model objects as "subjects of observations" (notify observers/listeners/subscribers).
19
    """
20
21
    @abstractmethod
22
    def attach(self, observer: ObserverInterface) -> None:
23
        """Attach an observer to the subject."""
24
        raise NotImplementedError
25
26
    @abstractmethod
27
    def detach(self, observer: ObserverInterface) -> None:
28
        """Detach an observer from the subject."""
29
        raise NotImplementedError
30
31
    @abstractmethod
32
    def notify(self) -> None:
33
        """Notify all observers about an event."""
34
        raise NotImplementedError
35
36
37
class Subject(SubjectInterface):
38
    """The Subject owns some important state and notifies observers when the state changes. Both the _state and _observers
39
    attributes can be overriden to accomodate for more complex scenarios."""
40
    def __new__(cls, *args, **kwargs):
41
        self_object = super().__new__(cls)
42
        self_object._observers = []  # type=List[ObserverInterface]
43
        self_object._state = None
44
        return self_object
45
46
    def add(self, *observers):
47
        self._observers.extend([_ for _ in observers])
48
    """
49
    List of subscribers. In real life, the list of subscribers can be stored
50
    more comprehensively (categorized by event type, etc.).
51
    """
52
    @property
53
    def state(self):
54
        return self._state
55
56
    @state.setter
57
    def state(self, state):
58
        self._state = state
59
60
    def attach(self, observer: ObserverInterface) -> None:
61
        self._observers.append(observer)
62
        print(f"\nATTACH:\nSubject:\n{self}\nOBSERVED BY\n{observer}")
63
64
    def detach(self, observer: ObserverInterface) -> None:
65
        self._observers.remove(observer)
66
67
    """
68
    The subscription management methods.
69
    """
70
71
    def notify(self) -> None:
72
        """Trigger an update in each subscriber/observer."""
73
        for observer in self._observers:
74
            observer.update(self)
75
76
"""
77
Concrete Observers react to the updates issued by the Subject they had been
78
attached to.
79
"""
80
class Observer(ObserverInterface):
81
    def update(self, subject: Subject) -> None:
82
        pass
83