07. Composite va Proxy: Fayl Tizimi va Biometrik Soqchi
🏛️ iOS Design Patterns — Mukammal Enterprise & Architecture Qo‘llanma
07. Structural: Composite va Proxy Pattern
"Daraxtsimon tuzilmalar (papka ichida papka, view ichida view) bilan ishlaganda alohida element va uning konteynerini bir xil boshqarishni istasangiz — Composite tanlaysiz. Agar biror og'ir yoki maxfiy obyekt oldiga 'soqchi' qo'ymoqchi bo'lsangiz — Proxy tanlaysiz."
1. Composite Pattern: Daraxtsimon Iyerarxiya
Composite — bu obyektlarni daraxtsimon tuzilmalarga guruhlash va alohida yakka obyekt (Leaf) hamda obyektlar guruhiga (Composite) bir xil interfeys orqali murojaat qilish imkonini beruvchi pattern.
graph TD
RootFolder["Papkalar (Root Folder) - Composite"] --> File1["Fayl 1 (Leaf) - 5 MB"]
RootFolder --> SubFolder["Media Papkasi - Composite"]
SubFolder --> File2["Rasm.png (Leaf) - 2 MB"]
SubFolder --> File3["Video.mp4 (Leaf) - 45 MB"]
style RootFolder fill:#131720,stroke:#bef264,stroke-width:2px
style SubFolder fill:#181d26,stroke:#7da2ce,stroke-width:1px
style File1 fill:#181d26,stroke:#60a5fa,stroke-width:1px
style File2 fill:#181d26,stroke:#60a5fa,stroke-width:1px
style File3 fill:#181d26,stroke:#60a5fa,stroke-width:1px
Swift 6 Real Kodi: Fayl Tizimi Hajmini Hisoblash
Chaqiruvchi bitta fayl yoki butun papkani tekshirayotganini bilishi shart emas. Har ikkalasi ham getSizeInMB() ga ega:
import Foundation
// 1. Umumiy Komponent Protokoli
public protocol FileSystemItem: Sendable {
var name: String { get }
func getSizeInMB() -> Double
}
// 2. Yakka Obyekt (Leaf - Barg)
public struct FileItem: FileSystemItem {
public let name: String
public let size: Double
public init(name: String, size: Double) {
self.name = name
self.size = size
}
public func getSizeInMB() -> Double {
return size
}
}
// 3. Konteyner (Composite - Shox)
public final class FolderItem: FileSystemItem {
public let name: String
private var children: [any FileSystemItem] = []
public init(name: String) {
self.name = name
}
public func add(_ item: any FileSystemItem) {
children.append(item)
}
// Rekursiv ravishda ichidagi barcha fayllar va ichki papkalar hajmini yig'adi
public func getSizeInMB() -> Double {
return children.reduce(0.0) { $0 + $1.getSizeInMB() }
}
}
iOS ekotizimida UIView va uning subviews iyerarxiyasi Composite patternining eng yorqin namunasidir!
2. Proxy Pattern: Ishonchli Soqchi
Proxy (Vakil) — bu boshqa bir obyektga kirishni nazorat qiluvchi, uning o'rnini bosuvchi va qo'shimcha vazifalarni (xavfsizlik, kechiktirib yuklash, kesh) bajaruvchi pattern.
flowchart LR
Client["Mijoz / ViewModel"] --> Proxy["ProtectionProxy\n(FaceID / Biometrika Tekshiruvchisi)"]
Proxy -->|"Foydalanuvchi tasdiqlandi"| RealService["Haqiqiy Bank O'tkazma Servisi"]
Proxy -->|"Bekor qilindi"| Reject["So'rov rad etildi (Xavfsizlik)"]
style Proxy fill:#131720,stroke:#bef264,stroke-width:2px
style RealService fill:#0d1f14,stroke:#4ade80,stroke-width:1px
style Reject fill:#251014,stroke:#f87171,stroke-width:1px
Proxy ning 3 Ta Asosiy Turi:
- Protection Proxy (Himoyachi): Amallarni bajarishdan oldin foydalanuvchining huquqlarini (Role-Based Access Control yoki Biometrika) tekshiradi.
- Virtual Proxy (Kechiktiruvchi): Og'ir obyektlarni xotiraga faqat kerak bo'lgandagina (Lazy Loading) yuklaydi.
- Caching Proxy (Keshlovchi): Bir marta olingan ma'lumotni keshda saqlab, serverga qayta so'rov yuborishdan saqlaydi.
3. Real Swift 6 Kodi: Xavfsiz To'lov Himoya Proksisi
import LocalAuthentication
// 1. Asosiy Servis Protokoli
public protocol MoneyTransferService: Sendable {
func transferFunds(amount: Double, recipient: String) async throws -> String
}
// 2. Haqiqiy Servis (Xavfli operatsiya)
public final class RealMoneyTransferService: MoneyTransferService {
public init() {}
public func transferFunds(amount: Double, recipient: String) async throws -> String {
return "\(amount) so'm \(recipient) ga muvaffaqiyatli o'tkazildi!"
}
}
// 3. Protection Proxy (FaceID so'rovchisi)
public final class SecureTransferProxy: MoneyTransferService {
private let realService: RealMoneyTransferService
public init(realService: RealMoneyTransferService = RealMoneyTransferService()) {
self.realService = realService
}
public func transferFunds(amount: Double, recipient: String) async throws -> String {
// FaceID / TouchID tekshiruvi
let context = LAContext()
var error: NSError?
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
throw TransferSecurityError.biometricsUnavailable
}
let authenticated = try await context.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Tranzaksiyani tasdiqlash uchun FaceID kerak"
)
guard authenticated else {
throw TransferSecurityError.authenticationFailed
}
// Faqat muvaffaqiyatli tekshiruvdan keyin haqiqiy servisga ruxsat beriladi!
return try await realService.transferFunds(amount: amount, recipient: recipient)
}
}
public enum TransferSecurityError: Error {
case biometricsUnavailable
case authenticationFailed
}
4. Interaktiv Savol-Javob (Self-Check Quiz)
<details> <summary><b>1-Savol: Swift tilidagi 'lazy var' xususiyati qaysi patternning ixcham shakli hisoblanadi?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Bu Virtual Proxy patternining til darajasidagi mexanizmidir! lazy var heavyData = loadData() yozganingizda, o'zgaruvchi xotirada darhol yaratilmaydi. Faqat birinchi marta unga murojaat qilingandagina yuklanish sodir bo'ladi. </details>
<details> <summary><b>2-Savol: Composite patternida xotira oqishi (Retain Cycle) xavfi qayerda yuzaga keladi?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Agar ichki bola elementlar (Children) o'zining ota papkasi yoki ota View'siga havola (parent) saqlasa: agar parent havolasi weak qilinmasa, ota va bola bir-birini kuchli (strong) ushlab turadi va butun daraxt xotiradan (Heap) o'chmay qoladi. </details>
5. Amaliy Topshiriq (Senior Challenge)
DynamicMenuComponent tizimini Composite patterni asosida quring:
MenuItem(oddiy bosiladigan havola) vaMenuGroup(ichida boshqaMenuItemlar yoki boshqa guruhlar bo'lishi mumkin bo'lgan menyu bo'limi) yarating.- Butun menyu iyerarxiyasini ekranda rekursiv ravishda konsolga chiroyli tabulyatsiya (
├──) bilan chiqaruvchirender()metodini yozing!