Azimjon Abdurasulov

11. Memento va Iterator: Form Snapshots va OOM Crashesiz Stream

🏛️ iOS Design Patterns — Mukammal Enterprise & Architecture Qo‘llanma

11. Behavioral: Memento va Iterator Pattern

"Agar foydalanuvchi 20 ta maydondan iborat anketani to'ldirayotganda kutilmaganda ilovadan chiqib ketsa va qayta kirganda hamma narsa o'chib ketganini ko'rsa — u ilovani o'chirib tashlaydi. Memento inkapsulyatsiyani buzmasdan holatni 'suratga' oladi. Iterator esa millionlab yozuvlarni RAM ni portlatmasdan oqimda o'qish imkonini beradi."


1. Memento Pattern: Obyekt Holatini Saqlash va Tiklash

Memento (Yodgorlik / Snapshot) — bu obyektning ichki maxfiy ma'lumotlarini (Encapsulation) tashqi dunyoga oshkor qilmagan holda, uning o'sha lahzadagi holatini saqlab qolish va kerak bo'lganda o'tmishdagi shu holatga to'liq qaytarish imkonini beruvchi pattern.

sequenceDiagram
    autonumber
    participant Form as RegistrationForm (Originator)
    participant Caretaker as DraftManager (Caretaker)

    Note over Form: Foydalanuvchi ma'lumot kiritmoqda...
    Form->>Form: makeSnapshot() -> FormMemento
    Form->>Caretaker: save(memento) (Diskka yozildi)
    
    Note over Form: 💥 Ilova yopildi yoki xotiradan o'chirildi!
    Note over Form: Yangi seans boshlandi...
    Caretaker->>Form: restore(memento)
    Note over Form: Barcha maydonlar 100% tiklandi!

2. Real Swift 6 Kodi: Anketani Saqlovchi Memento

Swift'da Codable protokoli Memento patternini amalga oshirishning eng toza va zamonaviy usulidir:

import Foundation

// 1. Originator (Holati saqlanadigan asosiy obyekt)
public final class JobApplicationForm {
    public var fullName: String = ""
    public var expectedSalary: Int = 0
    public var skills: [String] = []
    
    public init() {}
    
    // Memento (O'sha lahzadagi holat surati)
    public struct Memento: Codable, Sendable {
        fileprivate let name: String
        fileprivate let salary: Int
        fileprivate let skillsList: [String]
        fileprivate let timestamp: Date
    }
    
    /// Hozirgi holatni suratga olish
    public func createSnapshot() -> Memento {
        return Memento(
            name: fullName,
            salary: expectedSalary,
            skillsList: skills,
            timestamp: Date()
        )
    }
    
    /// Eski suratdan holatni qayta tiklash
    public func restore(from memento: Memento) {
        self.fullName = memento.name
        self.expectedSalary = memento.salary
        self.skills = memento.skillsList
        print("✅ Forma tiklandi! (Saqlangan vaqti: \(memento.timestamp))")
    }
}

// 2. Caretaker (Suratlarni diskda saqlovchi)
public final class DraftManager {
    private let userDefaults = UserDefaults.standard
    private let draftKey = "job_application_draft"
    
    public func saveDraft(_ memento: JobApplicationForm.Memento) {
        if let encoded = try? JSONEncoder().encode(memento) {
            userDefaults.set(encoded, forKey: draftKey)
        }
    }
    
    public func loadDraft() -> JobApplicationForm.Memento? {
        guard let data = userDefaults.data(forKey: draftKey),
              let memento = try? JSONDecoder().decode(JobApplicationForm.Memento.self, from: data) else {
            return nil
        }
        return memento
    }
}

3. Iterator Pattern: Millionlab Yozuvlarni RAM ni To'ldirmasdan O'qish

Iterator — bu to'plamning (Collection, List, Tree) ichki tuzilishini oshkor qilmasdan, uning elementlarini birma-bir ketma-ket aylanib chiqish (Traverse) imkonini beruvchi pattern.

flowchart LR
    Source["Og'ir 500 MB CSV Fayl\n(1,000,000 ta qator)"] --> Iterator["LargeFileIterator\n(IteratorProtocol)"]
    Iterator -->|"next() chaqirilganda"| RAM["Faqat 1 ta qator RAM'ga yuklanadi\n(Xotira sarfi: atigi 2 KB!)"]
    RAM --> Worker["Qayta ishlovchi prosessor"]

    style Source fill:#251014,stroke:#f87171,stroke-width:1px
    style Iterator fill:#131720,stroke:#bef264,stroke-width:2px
    style RAM fill:#0d1f14,stroke:#4ade80,stroke-width:1px

Swift'ning IteratorProtocol va Sequence:

Agar siz 1 millionta qatorni birdan lines = try String(contentsOf: file).components(separatedBy: "\n") qilib o'qisangiz — ilovangiz Jetsam Out-Of-Memory Crash bilan o'ladi! Iterator esa elementlarni faqat so'ralgandagina (Lazy Streaming) bittalab yuklaydi:

import Foundation

public struct InfiniteIDGenerator: Sequence, IteratorProtocol {
    private var currentID: Int = 1
    
    public mutating func next() -> Int? {
        let id = currentID
        currentID += 1
        return id
    }
}

// Ishlatilishi:
var generator = InfiniteIDGenerator()
print(generator.next()!) // 1
print(generator.next()!) // 2
print(generator.next()!) // 3

4. Interaktiv Savol-Javob (Self-Check Quiz)

<details> <summary><b>1-Savol: Memento va Command (Undo/Redo) o'rtasida qanday bog'liqlik bor?</b> (Yechimni ko'rish uchun bosing)</summary>

Tahlil va Yechim: Ular juda ko'p hollarda birga ishlatiladi! Command obyekti biror amalni bajarishdan oldin Originator'dan createSnapshot() orqali Memento olib, o'zining ichida saqlab qo'yadi. Agar foydalanuvchi "Undo" qilsa, Command o'sha saqlab qo'yilgan Mementoni Originator'ga qaytaradi (restore(memento)). </details>

<details> <summary><b>2-Savol: Swift'dagi 'for item in items' sikli qaysi pattern asosida ishlaydi?</b> (Yechimni ko'rish uchun bosing)</summary>

Tahlil va Yechim: Bu 100% Iterator Patternidir! Swift tili har qanday Sequence ni ko'rganda, orqa fonda uning makeIterator() metodini chaqiradi va while let item = iterator.next() siklini yurgizadi. </details>


5. Amaliy Topshiriq (Senior Challenge)

UserPreferencesOriginator sinfini quring:

  • Unda theme: String, fontSize: Double, notificationsEnabled: Bool maydonlari bo'lsin.
  • Foydalanuvchi sozlamalarni o'zgartirganda "Oldingi holatga qaytish" (Revert) imkonini beruvchi Memento arxitekturasini yarating!

Markdown manba

iOS Lessons