# 04. Creational: Builder va Prototype Pattern

> "Agar sizning konstruktoringizda 12 ta parametr bo'lib, ulardan 8 tasi ixtiyoriy (optional) bo'lsa — siz 'Telescoping Constructor' balosiga duchor bo'lgansiz. Builder bu boshog'riqni chiroyli va o'qishli oqimga aylantiradi."

---

## 1. Builder Pattern Nima va U Qaysi Muammoni Hal Qiladi?

**Builder** — bu ko'p bosqichli va ko'p parametrli murakkab obyektlarni bosqichma-bosqich, zanjirband uslubda (Method Chaining / Fluent API) yaratish imkonini beruvchi pattern.

### "Telescoping Constructor" Fojiasi:
```swift
// ❌ QO'RFINCHLI ANTI-PATTERN:
let request = URLRequest(
    url: url,
    cachePolicy: .useProtocolCachePolicy,
    timeoutInterval: 60,
    mainDocumentURL: nil,
    networkServiceType: .default,
    allowsCellularAccess: true,
    allowsExpensiveNetworkAccess: true,
    allowsConstrainedNetworkAccess: true,
    httpMethod: "POST",
    allHTTPHeaderFields: ["Authorization": "Bearer ..."],
    httpBody: bodyData
)
```
Bu kodni o'qish ham, yangi parametr qo'shish ham o'ta noqulay.

```mermaid
flowchart LR
    Start["Builder yaratish:\nURLRequestBuilder()"] --> SetURL[".setURL('/api/orders')"]
    SetURL --> SetMethod[".setMethod(.post)"]
    SetMethod --> SetAuth[".addBearerToken(token)"]
    SetAuth --> SetBody[".setJSONBody(payload)"]
    SetBody --> Build[".build() -> URLRequest"]

    style Start fill:#131720,stroke:#7da2ce,stroke-width:1px
    style Build fill:#131720,stroke:#bef264,stroke-width:2px
```

---

## 2. Real-World Swift 6 Kodi: Enterprise URLRequestBuilder

```swift
import Foundation

public enum HTTPMethod: String {
    case get = "GET"
    case post = "POST"
    case put = "PUT"
    case delete = "DELETE"
}

public final class URLRequestBuilder {
    private var baseURL: URL
    private var path: String = ""
    private var method: HTTPMethod = .get
    private var headers: [String: String] = [:]
    private var queryParams: [String: String] = [:]
    private var body: Data?
    private var timeout: TimeInterval = 30.0
    
    public init(baseURL: URL) {
        self.baseURL = baseURL
    }
    
    @discardableResult
    public func setPath(_ path: String) -> Self {
        self.path = path
        return self
    }
    
    @discardableResult
    public func setMethod(_ method: HTTPMethod) -> Self {
        self.method = method
        return self
    }
    
    @discardableResult
    public func addHeader(key: String, value: String) -> Self {
        self.headers[key] = value
        return self
    }
    
    @discardableResult
    public func addBearerToken(_ token: String) -> Self {
        self.headers["Authorization"] = "Bearer \(token)"
        return self
    }
    
    @discardableResult
    public func addQueryParam(key: String, value: String) -> Self {
        self.queryParams[key] = value
        return self
    }
    
    @discardableResult
    public func setJSONBody<T: Encodable>(_ object: T) throws -> Self {
        self.body = try JSONEncoder().encode(object)
        self.headers["Content-Type"] = "application/json"
        return self
    }
    
    public func build() throws -> URLRequest {
        var fullURL = baseURL.appendingPathComponent(path)
        
        if !queryParams.isEmpty {
            var components = URLComponents(url: fullURL, resolvingAgainstBaseURL: false)
            components?.queryItems = queryParams.map { URLQueryItem(name: $0.key, value: $0.value) }
            if let configuredURL = components?.url {
                fullURL = configuredURL
            }
        }
        
        var request = URLRequest(url: fullURL, timeoutInterval: timeout)
        request.httpMethod = method.rawValue
        request.httpBody = body
        for (key, value) in headers {
            request.addValue(value, forHTTPHeaderField: key)
        }
        return request
    }
}
```

### Ishlatilishi (Toza va O'qishli):
```swift
let request = try URLRequestBuilder(baseURL: URL(string: "https://api.azimjondev.uz")!)
    .setPath("/v1/orders/create")
    .setMethod(.post)
    .addBearerToken("jwt_secret_token_123")
    .addQueryParam(key: "currency", value: "UZS")
    .setJSONBody(OrderPayload(itemsCount: 3))
    .build()
```

---

## 3. Swift'dagi @resultBuilder: SwiftUI Qanday Qilib Builderni Tilga Kiritdi?

SwiftUI dagi har bir `VStack`, `HStack` yoki `List` aslida Swift'ning rasmiy **Result Builder** imkoniyatiga asoslangan:

```swift
@resultBuilder
public struct ViewBuilder { ... }
```

Siz quyidagicha yozganingizda:
```swift
VStack {
    Text("Sarlavha")
    Button("Bosish") {}
}
```
Swift kompilyatori orqa fonda `ViewBuilder.buildBlock(Text(...), Button(...))` chaqiruvini bajaradi. Bu Builder patternining zamonaviy deklarativ shaklidir!

---

## 4. Prototype Pattern: Nusxa Olish va Copy-on-Write (CoW)

**Prototype** — bu mavjud obyektning aniq nusxasini (klonini) yaratishga imkon beruvchi pattern.

### Shallow Copy vs Deep Copy Fojiasi:

```mermaid
flowchart TD
    subgraph Shallow["❌ Shallow Copy (Sayoz Nusxa)"]
        ObjA["Obyekt A"] --> Ref["Bir Xil Xotira Manzili (Shared Reference)"]
        ObjB["Obyekt B"] --> Ref
        ObjB -.->|"B o'zgarsa"| Corrupt["💥 A ham kutilmaganda o'zgarib ketadi!"]
    end

    subgraph Deep["✅ Deep Copy (Chuqur Nusxa)"]
        Obj1["Obyekt A"] --> Ref1["RAM Manzil #1"]
        Obj2["Obyekt B (Klon)"] --> Ref2["Yangi RAM Manzil #2"]
        Obj2 -.->|"B o'zgarsa"| Safe["A xavfsiz va o'zgarmas qoladi!"]
    end

    style Shallow fill:#251014,stroke:#f87171,stroke-width:1px
    style Deep fill:#0d1f14,stroke:#4ade80,stroke-width:1px
```

### Swift'da Prototype:
* **Structlar (Value Types):** Swift structlari tabiiy ravishda Prototype patternini o'z ichiga oladi:
  ```swift
  struct UserProfile { var name: String }
  var user1 = UserProfile(name: "Ali")
  var user2 = user1 // Avtomatik ravishda to'liq mustaqil klon! (Copy-on-Write)
  user2.name = "Vali" // user1 "Ali" bo'lib qoladi
  ```
* **Classlar (Reference Types):** Classlar bilan ishlaganda esa `NSCopying` protokolini amalga oshirish kerak bo'ladi:
  ```swift
  final class ComplexReport: NSCopying {
      var title: String
      var metrics: [String: Int]
      
      init(title: String, metrics: [String: Int]) {
          self.title = title
          self.metrics = metrics
      }
      
      // Deep Copy implementatsiyasi
      func copy(with zone: NSZone? = nil) -> Any {
          return ComplexReport(title: self.title, metrics: self.metrics)
      }
  }
  ```

---

## 5. Interaktiv Savol-Javob (Self-Check Quiz)

<details>
<summary><b>1-Savol: Nega Swift'da Builder metodlarida '@discardableResult' atributi yoziladi?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
Metod `return self` qaytargani sababli, agar chaqiruvchi ushbu qaytgan qiymatni alohida o'zgaruvchiga o'zlashtirmasa (masalan zanjir o'rtasida), Swift kompilyatori `Result of call to '...' is unused` degan ogohlantirish (warning) bermasligi uchun `@discardableResult` qo'yiladi.
</details>

<details>
<summary><b>2-Savol: Qachon oddiy Struct copy o'rniga Class uchun Prototype patternini maxsus yozish talab etiladi?</b> (Yechimni ko'rish uchun bosing)</summary>

**Tahlil va Yechim:**
Agar obyekt juda og'ir bo'lsa (masalan, grafika chizish loyihalarida millionlab poligonlardan iborat 3D model yoki rasm tahrirlagichdagi ko'p qatlamli Layer) va uni noldan qayta hisoblab yaratish juda ko'p CPU talab qilsa. Bunday holatda xotiradagi tayyor obyektni klonlab, faqat o'zgargan bir nechta xususiyatini almashtirish 100x tezroq bo'ladi.
</details>

---

## 6. Amaliy Topshiriq (Senior Challenge)

`PushNotificationPayloadBuilder` sinfini yarating:
* `.setTitle(_:)`, `.setBody(_:)`, `.setCategory(_:)`, `.setBadgeCount(_:)`, `.addCustomData(key:value:)` metodlariga ega bo'lsin.
* `.build()` metodi kamida `title` va `body` kiritilganini tekshirsin, agar kiritilmagan bo'lsa `NotificationBuildError.missingRequiredFields` xatosini tashlasin (throw qilsin)!
