' ============================================================ ' WALKGUIDE — DESIGN PATTERNS (GoF) ' Flutter × Spring Boot × In-Device AI ' Pattern 5 of 7: OBSERVER (Behavioral) ' ============================================================ @startuml WalkGuide_05_Observer skinparam monochrome false skinparam shadowing false skinparam defaultFontName Arial skinparam defaultFontSize 12 skinparam roundCorner 10 skinparam ArrowColor #555555 skinparam ArrowThickness 1.2 skinparam class { BackgroundColor #FAFAFA BorderColor #AAAAAA HeaderBackgroundColor #E8E8E8 FontColor #222222 StereotypeFontColor #666666 AttributeFontColor #333333 } skinparam package { BackgroundColor #F5F5F5 BorderColor #888888 FontColor #333333 FontStyle bold } skinparam note { BackgroundColor #FFFDE7 BorderColor #F9A825 FontColor #444444 FontSize 11 } ' ============================================================ ' PATTERN 5 — OBSERVER (Behavioral) ' ============================================================ package "⑤ Observer Pattern [Behavioral]" #F3E5F5 { abstract class "Cubit\n<>" as BlocSubject { # stateController : StreamController + emit(State state) + stream : Stream } class "WalkGuideCubit\n<>" as WalkGuideCubitObs { + start() + stop() + logObstacle() - _yoloDetector : YoloDetector - _ttsService : TtsService - _hapticService : HapticService } class "BlocBuilder\n<>" as BlocBuilderWidget { + builder(ctx, state) : Widget ' Rebuilds UI on every state emission } class "BlocListener\n<>" as BlocListenerWidget { + listener(ctx, state) : void ' Side effects: TTS, haptic, navigation } class "WebSocketService\n<>" as WebSocketObs { - _stompClient : StompClient + subscribe(destination) : Stream + onLocationUpdate : StreamController + onSosAlert : StreamController + onNotification : StreamController } class "GuardianMapScreen\n<>" as GuardianMapObs { + onLocationUpdate(LocationData) ' Updates flutter_map markers in real-time } BlocSubject <|-- WalkGuideCubitObs : extends WalkGuideCubitObs --> BlocBuilderWidget : emits state\n(rebuilds UI) WalkGuideCubitObs --> BlocListenerWidget : emits state\n(side effects) WebSocketObs --> GuardianMapObs : notifies\nlive location } note left of WebSocketObs Guardian subscribe topic: /topic/location/{userId} — live map /queue/sos/{guardianId} — SOS alert /queue/notif/{userId} — notifications STOMP over SockJS (stomp_dart_client) end note @enduml