1-bo‘lim

Naqsh nima va qachon kerak

Dizayn naqshi - bu kod emas, muammoni hal qilish usuli. Va u har doim ham kerak emas.

🕑 13 daqiqa o‘qish 📄 981 so‘z 👁 3 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Naqsh nima emas
  2. Muammo: har o'zgarishda if qo'shish
  3. Yechim: umumiy interfeys
  4. Naqsh bepul emas
  5. Uch guruh
  6. Naqshni tanish
  7. Bu darslikda nima bo'ladi
  8. Xulosa

Dizayn naqshi - takrorlanuvchi muammoga topilgan, nomi bor va sinovdan o'tgan yechim. U kutubxona emas, kod bo'lagi ham emas - u g'oya.

Naqsh nima emas #

Naqsh emasNima uchun
Ko'chirib olinadigan kodHar loyihada boshqacha yoziladi
Kutubxona yoki paketO'rnatib bo'lmaydi
AlgoritmAlgoritm - nima qilish, naqsh - qanday tuzish
Majburiy qoidaKo'p kodda naqshlar umuman kerak emas
Naqsh - bu umumiy so'z

Naqshlarning eng katta amaliy foydasi - muloqot.

"Bu yerda Strategy ishlatamiz" degan jumla bir soatlik tushuntirishning o'rnini bosadi. Hamkasbingiz darhol tushunadi: bir necha algoritm bo'ladi, ular bir xil interfeysga ega bo'ladi, va tanlov ish vaqtida qilinadi.

Bu 1994-yilda "Gang of Four" kitobi keltirgan asosiy o'zgarish edi: yechimlar allaqachon mavjud edi, lekin ularning nomi yo'q edi.

Shu sababli naqshni yodlash emas, tanish muhim: kodda uni ko'rganingizda "aha, bu Observer" deb ayta olish.

Muammo: har o'zgarishda if qo'shish #

Real misol - to'lov tizimi. Boshida bitta usul bor edi:

PHP
final class ToolovBoshqaruvchi
{
    public function tola(string $usul, int $summa): string
    {
        if ($usul === 'karta') {
            return "Kartadan {$summa} so'm yechildi";
        }
        return "Noma'lum usul";
    }
}

$b = new ToolovBoshqaruvchi();
echo $b->tola('karta', 50000), PHP_EOL;
echo $b->tola('payme', 50000), PHP_EOL;
Natija
Kartadan 50000 so'm yechildi
Noma'lum usul

Keyin Payme qo'shildi. Keyin Click. Keyin naqd pul. Keyin bo'lib to'lash. Olti oydan keyin metod shunday ko'rinadi:

PHP
final class OsganBoshqaruvchi
{
    public function tola(string $usul, int $summa): string
    {
        if ($usul === 'karta') {
            return "Kartadan {$summa} so'm yechildi";
        } elseif ($usul === 'payme') {
            return "Payme orqali {$summa} so'm";
        } elseif ($usul === 'click') {
            return "Click orqali {$summa} so'm";
        } elseif ($usul === 'naqd') {
            return "Naqd {$summa} so'm qabul qilindi";
        } elseif ($usul === 'bolib') {
            $oylik = intdiv($summa, 6);
            return "6 oyga bo'lindi: oyiga {$oylik} so'm";
        }
        return "Noma'lum usul";
    }
}

$b = new OsganBoshqaruvchi();
foreach (['karta', 'click', 'bolib'] as $usul) {
    echo $b->tola($usul, 60000), PHP_EOL;
}
Natija
Kartadan 60000 so'm yechildi
Click orqali 60000 so'm
6 oyga bo'lindi: oyiga 10000 so'm
Bu kodning uchta aniq muammosi bor

Kod ishlaydi. Lekin u har oy yomonlashadi:

MuammoOqibati
Yangi usul = shu faylni ochishIshlayotgan kodni buzish xavfi
Har usul bir joydaPayme kodi Click kodiga xalaqit beradi
Sinash qiyinBitta usulni sinash uchun butun sinf kerak

Eng muhimi - ochiq/yopiq tamoyili buzilgan (2-bo'lim): sinf kengaytirish uchun ochiq, o'zgartirish uchun yopiq bo'lishi kerak edi.

Bu yerda esa teskarisi: har yangi imkoniyat mavjud kodni o'zgartirishni talab qiladi.

Yechim: umumiy interfeys #

PHP
interface ToolovUsuli
{
    public function tola(int $summa): string;
}

final class Karta implements ToolovUsuli
{
    public function tola(int $summa): string
    {
        return "Kartadan {$summa} so'm yechildi";
    }
}

final class Click implements ToolovUsuli
{
    public function tola(int $summa): string
    {
        return "Click orqali {$summa} so'm";
    }
}

final class BolibTolash implements ToolovUsuli
{
    public function __construct(private int $oylar) {}

    public function tola(int $summa): string
    {
        $oylik = intdiv($summa, $this->oylar);
        return "{$this->oylar} oyga bo'lindi: oyiga {$oylik} so'm";
    }
}

function toladi(ToolovUsuli $usul, int $summa): string
{
    return $usul->tola($summa);
}
PHP
echo toladi(new Karta(), 60000), PHP_EOL;
echo toladi(new Click(), 60000), PHP_EOL;
echo toladi(new BolibTolash(6), 60000), PHP_EOL;
Natija
Kartadan 60000 so'm yechildi
Click orqali 60000 so'm
6 oyga bo'lindi: oyiga 10000 so'm

Bu Strategy naqshi (13-bo'lim). Endi yangi usul qo'shish uchun hech qanday mavjud faylni ochish shart emas - faqat yangi sinf yoziladi.

PHP
final class Naqd implements ToolovUsuli
{
    public function tola(int $summa): string
    {
        return "Naqd {$summa} so'm qabul qilindi";
    }
}

// mavjud kod umuman o'zgarmadi
echo toladi(new Naqd(), 60000), PHP_EOL;
echo "yangi sinf qo'shildi, eski kod tegilmadi", PHP_EOL;
Natija
Naqd 60000 so'm qabul qilindi
yangi sinf qo'shildi, eski kod tegilmadi
Bitta muammo, ikki xil tuzilma if zanjiri ToolovBoshqaruvchi if karta ... elseif payme ... elseif click ... elseif naqd ... elseif ... (har oy o'sadi) Yangi usul = shu faylni o'zgartirish Interfeys ToolovUsuli Karta Click Naqd Yangi Yangi usul = yangi fayl, eskisi tegilmaydi Naqshning mohiyati Kod miqdori ko'paydi - bitta sinf o'rniga to'rtta fayl. Lekin o'zgarish narxi tushdi. Naqsh doim shu almashuvni taklif qiladi.
Naqsh kodni qisqartirmaydi - u o'zgarishni arzonlashtiradi

Naqsh bepul emas #

PHP
// Muammo: ikkita son qo'shish kerak
function qoshish(int $a, int $b): int
{
    return $a + $b;
}

echo qoshish(2, 3), PHP_EOL;
Natija
5
Bunday kodga naqsh kerak emas

Yuqoridagi funksiyani "kengaytirish uchun ochiq" qilish mumkin: AmalInterfeysi, QoshishStrategiyasi, AmalFabrikasi, AmalKonteyneri...

Natijada uch qatorlik kod yuz qatorga aylanadi va hech kim uni tushunmaydi.

Naqsh - narx. U quyidagilarni talab qiladi:

NarxIzoh
Ko'proq fayl va sinfKodni kuzatish qiyinlashadi
Bilvosita chaqiruvlar"Bu metod aslida qayerda?"
Yangi hamkasbga tushuntirishNaqshni bilmasa - qiyin
Nosozlik qidirishStek chuqurroq bo'ladi

Bu narxni faqat haqiqiy foyda oqlaydi.

Amaliy qoida - uch marta qoidasi:

Necha martaNima qilish
Birinchi martaShunchaki yozing
Ikkinchi martaTakrorlashga chidang
Uchinchi martaEndi umumlashtiring

Ya'ni naqshni oldindan emas, muammo ko'ringandan keyin kiriting.

Uch guruh #

GuruhNima haqidaBo'limlar
Yaratuvchi (Creational)Obyekt qanday yaratiladi3-7
Strukturaviy (Structural)Obyektlar qanday birlashadi8-12
Xulq-atvor (Behavioral)Obyektlar qanday muloqot qiladi13-18
PHP
$guruhlar = [
    'Yaratuvchi' => ['Factory Method', 'Abstract Factory', 'Builder',
                     'Singleton', 'Prototype'],
    'Strukturaviy' => ['Adapter', 'Decorator', 'Facade', 'Composite', 'Proxy'],
    'Xulq-atvor' => ['Strategy', 'Observer', 'Command', 'Template Method',
                     'State', 'Chain of Responsibility'],
];

foreach ($guruhlar as $nom => $naqshlar) {
    printf("%-14s %d ta: %s%s", $nom, count($naqshlar),
        implode(', ', array_slice($naqshlar, 0, 3)) . '...', PHP_EOL);
}
echo "jami: ", array_sum(array_map('count', $guruhlar)), PHP_EOL;
Natija
Yaratuvchi     5 ta: Factory Method, Abstract Factory, Builder...
Strukturaviy   5 ta: Adapter, Decorator, Facade...
Xulq-atvor     6 ta: Strategy, Observer, Command...
jami: 16

Naqshni tanish #

Naqshlarni siz allaqachon ko'rgansiz - faqat nomini bilmagansiz.

Tanish narsaQaysi naqsh
array_map($fn, $arr) ga funksiya berishStrategy
Tugmaga hodisa ulash (addEventListener)Observer
PDO orqali turli bazalar bilan ishlashAdapter
Laravel Cache::get() fasadiFacade
Ma'lumotlar bazasi ulanishi bitta bo'lishiSingleton
foreach ni o'z sinfingizda ishlatishIterator
PHP
$sonlar = [1, 2, 3, 4, 5];

// Strategiya funksiya sifatida uzatiladi
$juftlar = array_filter($sonlar, fn(int $n): bool => $n % 2 === 0);
$kvadratlar = array_map(fn(int $n): int => $n ** 2, $sonlar);

echo 'juftlar: ', implode(', ', $juftlar), PHP_EOL;
echo 'kvadratlar: ', implode(', ', $kvadratlar), PHP_EOL;
Natija
juftlar: 2, 4
kvadratlar: 1, 4, 9, 16, 25
PHP da ko'p naqsh soddalashadi

array_filter ga funksiya uzatish - bu Strategy naqshining eng qisqa shakli. Klassik kitobda u interfeys va uchta sinf bilan yoziladi.

Bu muhim tushuncha: naqshning shakli tilga bog'liq.

TilStrategy qanday yoziladi
Eski JavaInterfeys + sinflar (majburiy)
PHP 8, Python, JSKo'pincha oddiy funksiya yetarli
HaskellShunchaki yuqori tartibli funksiya

Gang of Four kitobi 1994-yilda C++ va Smalltalk uchun yozilgan. Ba'zi naqshlar zamonaviy tillarda tilning o'z imkoniyatiga aylangan.

Shuning uchun darslikda har naqsh uchun ikkita savol beriladi:

  1. Bu naqsh qanday muammoni hal qiladi?
  2. PHP 8 da uni soddaroq yozish mumkinmi?

Bu darslikda nima bo'ladi #

Bo'limlarMavzu
1-2Naqsh nima, SOLID tamoyillari
3-7Yaratuvchi naqshlar
8-12Strukturaviy naqshlar
13-18Xulq-atvor naqshlari
19Naqshlarni noto'g'ri ishlatish
20Amaliy loyiha - bir necha naqsh birga
Amaliy topshiriq
  1. if/elseif zanjirli to'lov sinfini yozing.
  2. Unga to'rtinchi usul qo'shing va nechta joyni o'zgartirganingizni sanang.
  3. Xuddi shu masalani interfeys bilan qayta yozing.
  4. Yangi usul qo'shing - endi nechta mavjud fayl o'zgardi?
  5. Naqsh kod miqdorini oshirdimi yoki kamaytirdimi?
  6. "Uch marta qoidasi" ni o'z so'zlaringiz bilan tushuntiring.
  7. Uch guruhni va ularning farqini yozing.
  8. array_map da qaysi naqsh yashiringanini ayting.
  9. O'z kodingizdan naqshga o'xshash uchta joy toping.
  10. Qaysi kodda naqsh kerak emasligi haqida uchta misol yozing.

Xulosa #

  • Naqsh - kod emas, muammoni hal qilish usuli va umumiy so'z.
  • Uning eng katta foydasi - jamoada muloqot.
  • if/elseif zanjiri har o'zgarishda mavjud kodni ochishga majbur qiladi.
  • Interfeys yangi imkoniyatni yangi fayl bilan qo'shish imkonini beradi.
  • Naqsh kodni qisqartirmaydi - u o'zgarishni arzonlashtiradi.
  • Naqsh bepul emas: ko'proq fayl, bilvosita chaqiruv, murakkabroq nosozlik qidirish.
  • Uch marta qoidasi: uchinchi takrorlanishdan keyin umumlashtiring.
  • Uch guruh: yaratuvchi, strukturaviy, xulq-atvor.
  • Naqshning shakli tilga bog'liq - PHP 8 da ko'pi soddalashadi.
  • Har naqshda ikkita savol: qanday muammoni yechadi va soddaroq yo'l bormi.

Keyingi bo'limda SOLID tamoyillarini ko'ramiz - deyarli barcha naqshlar shulardan kelib chiqadi.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.