┌─────────────────────────────────┐ │Subject │ ┌──────────────────────────────────────┐ ┌─┐ ├─────────────────────────────────┤ │Observer │ │ │ │-list $observers │ ├──────────────────────────────────────┤ ├─┤ │+attach(Observer $observer): void│---│+update(Subject $changedSubject): void│ └─┘ │+detach(Observer $observer): void│ │+equals(mixed $other): bool │ │+notify(): void │ └──────────────────────────────────────┘ └─────────────────────────────────┘ ┌─────────────────┐ ┌──────────────────────────────────────┐ │ConcreteSubject │ │ConcreteObserver │ ┌─┐ ├─────────────────┤ ├──────────────────────────────────────┤ ┌─┐ │ │ │-$state │ │-$state │ │ │ ├─┤ │+getState() │-------│-ConcreteSubject $subject │ ├─┤ └─┘ │+setState($state)│ │+update(Subject $changedSubject): void│ └─┘ └─────────────────┘ │+equals(mixed $other): bool │ └──────────────────────────────────────┘