' ============================================================
' WALKGUIDE — DESIGN PATTERNS (GoF)
' Flutter × Spring Boot × In-Device AI
' Pattern 2 of 7: SINGLETON (Creational)
' ============================================================

@startuml WalkGuide_02_Singleton

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 2 — SINGLETON (Creational)
' ============================================================

package "②  Singleton Pattern  [Creational]" #EEF0FF {

    class "GetIt\n<<ServiceLocator>>" as GetIt {
        - {static} _instance : GetIt
        + {static} instance : GetIt
        + registerSingleton<T>(T)
        + get<T>() : T
    }

    class "TtsService\n<<Singleton>>" as TtsService {
        - {static} _instance : TtsService
        - _flutterTts : FlutterTts
        + speak(String text)
        + speakImmediate(String text)
        + stop()
        + setLanguage(String lang)
    }

    class "SttService\n<<Singleton>>" as SttService {
        - {static} _instance : SttService
        - _speechToText : SpeechToText
        + startListening()
        + stopListening()
        + onResult : Stream<String>
    }

    class "YoloDetector\n<<Singleton>>" as YoloDetector {
        - {static} _instance : YoloDetector
        - _interpreter : Interpreter
        - _labels : List<String>
        + loadModel()
        + detect(CameraImage) : List<DetectionResult>
        + isRunning : bool
    }

    class "WebSocketService\n<<Singleton>>" as WebSocketService {
        - {static} _instance : WebSocketService
        - _stompClient : StompClient
        + connect(String token)
        + subscribe(String destination)
        + disconnect()
    }

    class "AgoraService\n<<Singleton>>" as AgoraService {
        - {static} _instance : AgoraService
        - _engine : RtcEngine
        + joinChannel(token, channel, uid)
        + leaveChannel()
        + muteLocalAudio(bool)
    }

    GetIt --> TtsService : registers &\nmanages
    GetIt --> SttService : registers &\nmanages
    GetIt --> YoloDetector : registers &\nmanages
    GetIt --> WebSocketService : registers &\nmanages
    GetIt --> AgoraService : registers &\nmanages
}

note right of GetIt
  injection_container.dart:
  sl.registerSingleton<TtsService>(TtsService())
  sl.registerSingleton<YoloDetector>(YoloDetector())
  sl.registerSingleton<WebSocketService>(WebSocketService())
  Satu instance untuk seluruh lifecycle app.
end note

@enduml
