Builder - Dasturlashda Patternlar. (5-qism)

07.06.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Patternlar & SOLID | 10 daqiqa o'qish
Builder - Dasturlashda Patternlar. (5-qism)

Builder o'zbekchaga tarjima qilganda Quruvchi bo'ladi. Biz uni asl terminda ishlatganimiz qulay va oson bo'ladi.

Builder - bu obyekt yaratishga oid design pattern bo‘lib, murakkab obyektlarni bosqichma-bosqich yaratish yoki qurish imkonini beradi.

Bu pattern bir xil qurish jarayonidan foydalanib, obyektning turli ko‘rinishlarini yaratishga yordam beradi.

🚩 Muammo

Tasavvur qiling, sizda juda murakkab obyekt bor. Uni yaratish uchun ko‘plab maydonlar, ichma-ich obyektlar va sozlamalarni ketma-ket to‘ldirish kerak.

Bunday holatda kod odatda:

  • juda katta konstruktor ichiga tiqib yuboriladi;

  • yoki obyekt yaratish logikasi har xil joylarga tarqalib ketadi.

Masalan, House - Uy obyektini olaylik.

Oddiy uy qurish uchun:

  • 4 ta devor kerak;

  • eshik qo‘yiladi;

  • derazalar o‘rnatiladi;

  • tom yopiladi.

Lekin katta, yorug', bog‘i, basseyni va boshqa qulayliklari bor uy kerak bo‘lsa-chi?

Eng oddiy yo‘l -House classidan ko‘plab subclasslar yaratish:

  • House - Uy (Asosiy class/obyekt)

  • HouseWithGarage - Garajli uy

  • HouseWithSwimmingPool - Basseynli uy

  • HouseWithFancyStatues - Hashamatli haykalli uy

  • HouseWithGarden - Bog'li uy

Builder - Dasturlashda Patternlar. (5-qism)

Lekin bu yondashuvda classlar soni juda ko‘payib ketadi. Har bir yangi parametr - masalan, devor rangi yoki tom materiali - yana yangi kombinatsiyalarni talab qiladi.

Boshqa yo‘l - bitta ulkan konstruktor yaratish:

new House(walls, doors, windows, roof, pool, garden, garage, color, material);

Bu subclasslar sonini kamaytiradi, lekin boshqa muammo tug‘diradi: konstruktor juda katta va tushunarsiz bo‘lib qoladi.

Uyda quyidagilar bo‘lishi mumkin:

walls
doors
windows
roof
garage
garden
pool

Agar bularning hammasini constructor orqali bersak, kod juda chalkash bo‘lib ketadi:

House house = new House(4, 2, 6, true, false, true, false);

Bu kodni ko‘rgan odam darrov tushunmaydi:

  • 4 nima?

  • 2 nima?

  • true nimani bildiradi?

  • false qaysi parametr?

Shuning uchun bunday constructorlar o‘qishga qiyin va xatoga moyil bo‘ladi.

Ko‘p parametrlar doim ham kerak bo‘lmaydi. Masalan, har bir uyda basseyn bo‘lmaydi. Demak, basseyn bilan bog‘liq parametrlar ko‘p holatda ishlatilmaydi.


💡 Yechim

Builder pattern obyekt yaratish jarayonini obyektning o‘zidan ajratadi.

Ya’ni obyektni yaratish ishini alohida obyekt - Builder bajaradi.

Uy birdaniga tayyor bo‘lib qolmaydi. Avval poydevor qilinadi, keyin devor, keyin tom, keyin eshik-deraza qo‘yiladi.

Obyekt yaratish bir nechta bosqichlarga bo‘linadi:

buildWalls()
buildDoors()
buildWindows()
buildRoof()
buildPool()
buildGarden()

Kerakli obyektni yaratish uchun faqat kerakli bosqichlar chaqiriladi.cHar bir qadam alohida bajariladi.

Masalan:

  • oddiy uy uchun devor, eshik, deraza va tom yetarli;

  • hashamatli uy uchun qo‘shimcha bog', basseyn va garaj qo‘shiladi.

Eng muhimi, bir xil qurish bosqichlari turli builderlarda turlicha bajarilishi mumkin.

Masalan:

  • yog‘och uy builderi devorlarni yog‘ochdan quradi;

  • tosh uy builderi devorlarni toshdan quradi;

  • hashamatli uy builderi qimmat materiallardan foydalanadi.

Builder obyektni tushunarli qilib yaratishga yordam beradi:

House house = new HouseBuilder()
        .walls(4)
        .doors(2)
        .windows(6)
        .hasGarden(true)
        .hasGarage(false)
        .build();

Bu kod ancha tushunarli.

Endi ko‘rib turibmiz:

  • uyda 4 ta devor bor;

  • 2 ta eshik bor;

  • 6 ta deraza bor;

  • bog' bor;

  • garaj yo‘q.

Shu orqali bir xil qurish jarayoni bilan turli xil obyektlar olish mumkin.


Director nima?

Ba’zan qurish bosqichlarini tartib bilan chaqiradigan alohida class yaratiladi. Bu class Director deb ataladi.

Director nima qiladi?

U obyektni qanday tartibda qurishni biladi.

Builder esa real qurish ishini bajaradi.

Masalan:

director.constructSimpleHouse(builder);
director.constructLuxuryHouse(builder);

Director majburiy emas. Builder metodlarini klient koddan to‘g‘ridan-to‘g‘ri chaqirish ham mumkin.

Lekin Director foydali bo‘ladi, agar sizda bir nechta standart konfiguratsiyalar bo‘lsa:

  • oddiy uy;

  • katta uy;

  • basseynli uy;

  • hashamatli uy.

Bu holatda obyekt yaratish tartibi Director ichida saqlanadi.


🧬 Struktura

Builder pattern odatda quyidagi qismlardan iborat bo‘ladi:

1. Builder interfeysi

Qurish bosqichlarini e’lon qiladi.

Masalan:

buildEngine()
buildSeats()
buildGPS()

2. Concrete Builder

Aniq builder classlari. Har biri qurish bosqichlarini o‘ziga xos tarzda bajaradi.

Masalan:

CarBuilder
ManualBuilder

Biri mashina yaratadi, boshqasi shu mashina uchun qo‘llanma yaratadi.

3. Product

Yaratilayotgan obyekt.

Masalan:

Car
Manual
House

Turli builderlar yaratgan productlar bir xil interfeysga ega bo‘lishi shart emas.

4. Director

Qurish bosqichlarining tartibini belgilaydi.

Masalan:

constructSportsCar()
constructSUV()
constructSimpleCar()

5. Client

Builder va Director obyektlarini yaratadi va kerakli natijani oladi.


Psevdokod misoli

Masalan, avtomobil yaratish kerak.

Avtomobil murakkab obyekt:

  • motor;

  • o‘rindiqlar;

  • eshiklar;

  • navigatsiya;

  • kompyuter tizimi;

  • xavfsizlik tizimlari.

Bularni bitta katta konstruktor orqali berish noqulay.

Shuning uchun alohida CarBuilder yaratiladi.

builder.setSeats(4);
builder.setEngine("Sport engine");
builder.setGPS(true);

Client builder bilan to‘g‘ridan-to‘g‘ri ishlashi mumkin. Yoki bu ishni Director’ga topshiradi.

Masalan:

director.constructSportsCar(builder);

Yana qiziq tomoni: xuddi shu bosqichlar yordamida mashinaning texnik qo‘llanmasini ham yaratish mumkin.

Bitta builder mashinani yig‘adi, ikkinchi builder esa shu mashina haqida manual yaratadi.

Ya’ni bir xil qurish jarayoni:

setSeats()
setEngine()
setGPS()

bir holatda Car yaratadi, boshqa holatda Manual yaratadi.

// Builder bir xil qurilish jarayonidan foydalanib,
// turli mahsulotlar yarata oladi.
class Car {
    // Avtomobillar komplektatsiyasi bo'yicha farq qilishi mumkin:
    // dvigatel turi, o'rindiqlar soni, GPS va navigatsiya
    // tizimi bo'lishi yoki bo'lmasligi va hokazo.
    // Bundan tashqari, avtomobillar shahar, sport yoki
    // yoqsiz yo'l uchun bo'lishi mumkin.
}

class Manual {
    // Berilgan avtomobil konfiguratsiyasi uchun
    // foydalanuvchi qo'llanmasi.
}


// Builder interfeysi mahsulotni sozlashning barcha
// mumkin bo'lgan bosqichlari va qadamlarini e'lon qiladi.
interface Builder {
    void reset();
    void setSeats(int number);
    void setEngine(Engine engine);
    void setTripComputer(boolean value);
    void setGPS(boolean value);
}

// Barcha konkret builderlar umumiy interfeysni
// o'z usullarida amalga oshiradi.
class CarBuilder implements Builder {
    private Car car;

    public void reset() {
        // "car" maydoniga yangi Car obyektini joylashtirish.
        this.car = new Car();
    }

    public void setSeats(int number) {
        // Ko'rsatilgan miqdordagi o'rindiqlarni o'rnatish.
    }

    public void setEngine(Engine engine) {
        // Berilgan dvigatalni o'rnatish.
    }

    public void setTripComputer(boolean value) {
        // Berilgan navigatsiya tizimini o'rnatish.
    }

    public void setGPS(boolean value) {
        // GPS o'rnatish yoki olib tashlash.
    }

    public Car getResult() {
        // Joriy avtomobil obyektini qaytarish.
        return this.car;
    }
}

// Boshqa yaratuvchi patternlardan farqli o'laroq, bu yerda
// mahsulotlar umumiy ajdodga ega bo'lishi shart emas.
// Builderlar bir-biridan butunlay farq qiluvchi
// mahsulotlar yarata oladi.
class CarManualBuilder implements Builder {
    private Manual manual;

    public void reset() {
        // "manual" maydoniga yangi Manual obyektini joylashtirish.
        this.manual = new Manual();
    }

    public void setSeats(int number) {
        // Mashinada nechta o'rin borligini tavsiflash.
    }

    public void setEngine(Engine engine) {
        // Qo'llanmaga dvigatel tavsifini qo'shish.
    }

    public void setTripComputer(boolean value) {
        // Qo'llanmaga navigatsiya tizimi tavsifini qo'shish.
    }

    public void setGPS(boolean value) {
        // Ko'rsatmaga GPS bo'yicha yo'riqnoma qo'shish.
    }

    public Manual getResult() {
        // Joriy qo'llanma obyektini qaytarish.
        return this.manual;
    }
}


// Director builderni qaysi tartibda ishlatish kerakligini biladi,
// shunday qilib mahsulotning u yoki bu versiyasini olish mumkin.
// E'tibor bering: director builder bilan umumiy interfeys orqali
// ishlaydi, shu sababli u builder qaysi mahsulotni
// tayyorlayotganini bilmaydi.
class Director {
    public void constructSportsCar(Builder builder) {
        builder.reset();
        builder.setSeats(2);
        builder.setEngine(new SportEngine());
        builder.setTripComputer(true);
        builder.setGPS(true);
    }
}


// Director konkret builder obyektini mijozdan (ilovadan) oladi.
// Ilova o'zi qaysi builderni ishlatish kerakligini biladi,
// chunki u qaysi mahsulotni olishni xohlayotganini biladi.
class Application {
    public void makeCar() {
        Director director = new Director();

        CarBuilder builder = new CarBuilder();
        director.constructSportsCar(builder);
        Car car = builder.getResult();

        CarManualBuilder manualBuilder = new CarManualBuilder();
        director.constructSportsCar(manualBuilder);

        // Tayyor mahsulotni builder qaytaradi, chunki director
        // ko'pincha konkret builder va mahsulot klasslarini
        // bilmaydi va ularga bog'liq emas.
        Manual manual = manualBuilder.getResult();
    }
}


Qachon ishlatiladi?

1. Konstruktor juda kattalashib ketganda

Agar classda 10 ta yoki undan ko‘p optional parametr bo‘lsa, constructor chaqirish noqulay bo‘ladi.

Masalan, bunday kodni o‘qish qiyin.:

new House(4, 2, true, false, true, "red", "wood", null, null);

Builder bilan esa ancha tushunarli.:

House house = new HouseBuilder()
        .walls(4)
        .doors(2)
        .hasGarden(true)
        .material("wood")
        .build();

2. Bir obyektning turli ko‘rinishlarini yaratish kerak bo‘lsa

Masalan:

  • yog‘och uy;

  • tosh uy;

  • temir-beton uy.

    Bosqichlar bir xil, lekin bajarilishi har xil.


3. Murakkab ichma-ich obyektlar yaratishda

Masalan, daraxtsimon strukturalar yoki Composite pattern obyektlarini yig‘ishda Builder foydali bo‘ladi.

Builder obyektni bosqichma-bosqich yaratadi va obyekt to‘liq tayyor bo‘lmaguncha tashqi kodga bermaydi.

Bu esa klient kodning "yarim tayyor" yoki noto‘g‘ri obyekt bilan ishlashining oldini oladi.


Amalga oshirish bosqichlari

  1. Avval obyekt yaratish jarayonini umumiy bosqichlarga ajrating.

  2. Shu bosqichlarni Builder interfeysida yozing.

  3. Har bir obyekt ko‘rinishi uchun alohida builder class yarating.

  4. Har bir builder ichida o‘ziga xos qurish logikasini yozing.

  5. Natijani olish uchun getResult() yoki build() metodini qo‘shing.

  6. Kerak bo‘lsa, Director classini yarating. U qurish bosqichlarini kerakli tartibda chaqiradi.

  7. Client kod builder va director bilan ishlaydi, tayyor obyektni esa builderdan oladi.


Afzalliklari

Builder patternning foydalari:

  • murakkab obyektlarni bosqichma-bosqich yaratadi;

  • bitta qurish jarayoni orqali turli productlar yaratish mumkin;

  • katta konstruktorlardan qutqaradi;

  • obyekt yaratish logikasini biznes logikadan ajratadi;

  • kodni o‘qish va tushunish osonlashadi.


Kamchiliklari

Builder patternning minuslari ham bor:

  • qo‘shimcha classlar soni ko‘payadi;

  • oddiy obyektlar uchun ortiqcha murakkablik bo‘lishi mumkin;

  • client kod ba’zan aniq builder classlariga bog‘lanib qoladi;

  • Director har doim ham kerak bo‘lmaydi.


Boshqa patternlar bilan aloqasi

  • Ko‘p arxitekturalar avval Factory Method bilan boshlanadi, keyin murakkablik oshganda Abstract Factory, Prototype yoki Builder tomonga o‘tadi.

  • Builder murakkab obyektni bosqichma-bosqich yaratadi.

  • Abstract Factory esa bir-biriga bog‘liq obyektlar oilasini yaratishga xizmat qiladi.

  • Builder obyektni faqat barcha bosqichlar tugagandan keyin qaytaradi.

  • Abstract Factory esa obyektni darhol yaratib qaytaradi.

  • Builder yordamida Composite pattern’dagi daraxtsimon obyektlarni yig‘ish mumkin.

  • Builder pattern Bridge pattern shaklida ham qurilishi mumkin: Director - abstraction, builderlar esa implementation vazifasini bajaradi.(Kelajakda ko'rib chiqamiz.)

  • Abstract Factory, Builder va Prototype patternlari Singleton orqali ham amalga oshirilishi mumkin.


Qisqa xulosa

Builder pattern murakkab obyektlarni toza, tushunarli va bosqichma-bosqich yaratish uchun ishlatiladi.

U ayniqsa quyidagi holatlarda foydali:

  • konstruktor parametrlari juda ko‘p bo‘lsa;

  • obyektning turli konfiguratsiyalari bo‘lsa;

  • yaratish jarayoni murakkab bo‘lsa;

  • obyektni yarim tayyor holatda ishlatish xavfli bo‘lsa.

Oddiy qilib aytganda:

Builder - bu murakkab obyektni "birdaniga emas", balki kerakli qismlarini ketma-ket qo‘shib yig‘ish usuli.

Frameworklarda ko'zingiz tushgan bo'lsa shu patternlar ishlatiladi. Bu patternlar yaxshi o'rganib o'zingiz mustaqil framework yasay olasiz.