10. State va Chain of Responsibility: FSM va Interceptor Pipeline
🏛️ iOS Design Patterns — Mukammal Enterprise & Architecture Qo‘llanma
10. Behavioral: State va Chain of Responsibility
"Agar siz audio pleer yoki buyurtma holatini boshqarish uchun bitta ViewModel ichida 30 ta
if (isPlaying && !isPaused && hasConnection)shartlarini yozayotgan bo'lsangiz — siz portlovchi minalar maydonida yurasiz. State patterni bu holatlarni sof matematik Holat Mashinasiga (FSM) aylantiradi."
1. State Pattern: Chekli Holat Mashinasi (FSM)
State (Holat) — bu obyektning ichki holati o'zgarganda, uning tashqi xatti-harakati va metodlarining reaksiyasi butunlay boshqacha bo'lishiga imkon beruvchi pattern. Obyekt go'yo o'z sinfini o'zgartirgandek taassurot qoldiradi.
stateDiagram-v2
direction LR
[*] --> Idle: Ilova ochildi
Idle --> Buffering: play() chaqirildi
Buffering --> Playing: Buffer to'ldi
Playing --> Paused: pause() bosildi
Paused --> Playing: play() bosildi
Playing --> Failed: Tarmoq uzildi
Failed --> Idle: retry() yoki stop()
2. Real Swift 6 Kodi: Audio Player Holat Mashinasi
Har bir holat alohida sinfga chiqariladi:
import Foundation
// 1. Holat Protokoli
public protocol AudioPlayerState: Sendable {
func play(context: AudioPlayerContext)
func pause(context: AudioPlayerContext)
func stop(context: AudioPlayerContext)
}
// 2. Kontekst (Pleyerning o'zi)
@MainActor
public final class AudioPlayerContext {
private var state: any AudioPlayerState
public init() {
self.state = IdleState()
}
public func setState(_ newState: any AudioPlayerState) {
print("🔄 [State O'tishi] -> \(type(of: newState))")
self.state = newState
}
public func play() { state.play(context: self) }
public func pause() { state.pause(context: self) }
public func stop() { state.stop(context: self) }
}
// 3. Aniq Holatlar (Concrete States)
public struct IdleState: AudioPlayerState {
public func play(context: AudioPlayerContext) {
print("▶️ Qo'shiq yuklanmoqda... (Buffering holatiga o'tish)")
context.setState(BufferingState())
}
public func pause(context: AudioPlayerContext) {
print("⚠️ Hozir hech narsa yangramayapti, pauza qilib bo'lmaydi.")
}
public func stop(context: AudioPlayerContext) {}
}
public struct BufferingState: AudioPlayerState {
public func play(context: AudioPlayerContext) {
print("⏳ Qo'shiq allaqachon yuklanmoqda, kuting...")
}
public func pause(context: AudioPlayerContext) {
print("Yuklanish to'xtatildi.")
context.setState(IdleState())
}
public func stop(context: AudioPlayerContext) {
context.setState(IdleState())
}
}
public struct PlayingState: AudioPlayerState {
public func play(context: AudioPlayerContext) {
print("Qo'shiq allaqachon ijro etilmoqda.")
}
public func pause(context: AudioPlayerContext) {
print("⏸ Ijro pauza qilindi.")
context.setState(PausedState())
}
public func stop(context: AudioPlayerContext) {
print("⏹ Ijro to'xtatildi.")
context.setState(IdleState())
}
}
public struct PausedState: AudioPlayerState {
public func play(context: AudioPlayerContext) {
print("▶️ Ijro davom ettirilmoqda...")
context.setState(PlayingState())
}
public func pause(context: AudioPlayerContext) {}
public func stop(context: AudioPlayerContext) {
context.setState(IdleState())
}
}
3. Chain of Responsibility: Tarmoq Interceptorlar Quvuri
Chain of Responsibility (Mas'uliyat Zanjiri) — bu so'rovni bir nechta qayta ishlovchilar (Handlers) zanjiri orqali o'tkazish imkonini beruvchi pattern. Har bir halqa so'rovni o'zi tekshiradi, o'zgartiradi va keyingisiga uzatadi.
flowchart LR
Request["Chiquvchi Tarmoq So'rovi"] --> H1["1. AuthTokenInterceptor\n(Bearer tokenni kiritadi)"]
H1 --> H2["2. DeviceHeaderInterceptor\n(App Versiya, OS versiyani qo'shadi)"]
H2 --> H3["3. NetworkLoggingInterceptor\n(cURL formatda log yozadi)"]
H3 --> Server["Haqiqiy Serverga Chiqish"]
style H1 fill:#181d26,stroke:#7da2ce,stroke-width:1px
style H2 fill:#181d26,stroke:#7da2ce,stroke-width:1px
style H3 fill:#181d26,stroke:#bef264,stroke-width:2px
Swift 6 Interceptor Kodi:
import Foundation
public protocol RequestInterceptor: Sendable {
var next: (any RequestInterceptor)? { get set }
func intercept(request: URLRequest) async throws -> URLRequest
}
// 1. Token Qo'shuvchi Halqa
public final class AuthTokenInterceptor: RequestInterceptor {
public var next: (any RequestInterceptor)?
public func intercept(request: URLRequest) async throws -> URLRequest {
var modified = request
modified.addValue("Bearer sample_jwt_token", forHTTPHeaderField: "Authorization")
if let next = next {
return try await next.intercept(request: modified)
}
return modified
}
}
// 2. Qurilma Ma'lumotlarini Qo'shuvchi Halqa
public final class DeviceHeadersInterceptor: RequestInterceptor {
public var next: (any RequestInterceptor)?
public func intercept(request: URLRequest) async throws -> URLRequest {
var modified = request
modified.addValue("iOS 18.0", forHTTPHeaderField: "X-OS-Version")
modified.addValue("1.5.0", forHTTPHeaderField: "X-App-Version")
if let next = next {
return try await next.intercept(request: modified)
}
return modified
}
}
4. Interaktiv Savol-Javob (Self-Check Quiz)
<details> <summary><b>1-Savol: iOS tizimidagi 'UIResponder Chain' qaysi pattern asosida qurilgan?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Nomidan ko'rinib turganidek, bu 100% Chain of Responsibility patternidir! Foydalanuvchi ekranga tekkanda (Touch Event), iOS avval eng pastdagi View'ga so'rov beradi. Agar u javob bermasa, uning ota View'si (superview), keyin UIViewController, keyin UIWindow va oxiri UIApplication gacha zanjir bo'ylab yuqoriga uzatiladi. </details>
<details> <summary><b>2-Savol: State patternida yangi holat qo'shish qanchalik oson?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Juda oson (Open/Closed Principle). Mavjud kodlardagi birorta if-else ga tegmaysiz. Masalan, pleyerga AdvertisementState (reklama holati) qo'shish kerak bo'lsa, shunchaki yangi struct AdvertisementState: AudioPlayerState yaratiladi va kerakli o'tish nuqtasiga ulanadi. </details>
5. Amaliy Topshiriq (Senior Challenge)
OrderFSM (Buyurtma Holat Mashinasi)ni quring:
- Holatlar:
CreatedState->PaidState->CookingState->DeliveringState->DeliveredState. - Shart: Agar buyurtma
DeliveringStateholatiga o'tgan bo'lsa, uni bekor qilib (cancel()) bo'lmasin (xatolik chiqsin). FaqatCreatedStatevaPaidStateholatlaridagina bekor qilishga ruxsat berilsin!