1-bo‘lim
Naqsh nima va qachon kerak
Dizayn naqshi - bu kod emas, muammoni hal qilish usuli. Va u har doim ham kerak emas.
Ushbu bo‘lim mundarijasi
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 emas | Nima uchun |
|---|---|
| Ko'chirib olinadigan kod | Har loyihada boshqacha yoziladi |
| Kutubxona yoki paket | O'rnatib bo'lmaydi |
| Algoritm | Algoritm - nima qilish, naqsh - qanday tuzish |
| Majburiy qoida | Ko'p kodda naqshlar umuman kerak emas |
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:
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;
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:
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;
}
Kartadan 60000 so'm yechildi
Click orqali 60000 so'm
6 oyga bo'lindi: oyiga 10000 so'm
Kod ishlaydi. Lekin u har oy yomonlashadi:
| Muammo | Oqibati |
|---|---|
| Yangi usul = shu faylni ochish | Ishlayotgan kodni buzish xavfi |
| Har usul bir joyda | Payme kodi Click kodiga xalaqit beradi |
| Sinash qiyin | Bitta 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 #
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);
}
echo toladi(new Karta(), 60000), PHP_EOL;
echo toladi(new Click(), 60000), PHP_EOL;
echo toladi(new BolibTolash(6), 60000), PHP_EOL;
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.
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;
Naqd 60000 so'm qabul qilindi
yangi sinf qo'shildi, eski kod tegilmadi
Naqsh bepul emas #
// Muammo: ikkita son qo'shish kerak
function qoshish(int $a, int $b): int
{
return $a + $b;
}
echo qoshish(2, 3), PHP_EOL;
5
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:
| Narx | Izoh |
|---|---|
| Ko'proq fayl va sinf | Kodni kuzatish qiyinlashadi |
| Bilvosita chaqiruvlar | "Bu metod aslida qayerda?" |
| Yangi hamkasbga tushuntirish | Naqshni bilmasa - qiyin |
| Nosozlik qidirish | Stek chuqurroq bo'ladi |
Bu narxni faqat haqiqiy foyda oqlaydi.
Amaliy qoida - uch marta qoidasi:
| Necha marta | Nima qilish |
|---|---|
| Birinchi marta | Shunchaki yozing |
| Ikkinchi marta | Takrorlashga chidang |
| Uchinchi marta | Endi umumlashtiring |
Ya'ni naqshni oldindan emas, muammo ko'ringandan keyin kiriting.
Uch guruh #
| Guruh | Nima haqida | Bo'limlar |
|---|---|---|
| Yaratuvchi (Creational) | Obyekt qanday yaratiladi | 3-7 |
| Strukturaviy (Structural) | Obyektlar qanday birlashadi | 8-12 |
| Xulq-atvor (Behavioral) | Obyektlar qanday muloqot qiladi | 13-18 |
$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;
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 narsa | Qaysi naqsh |
|---|---|
array_map($fn, $arr) ga funksiya berish | Strategy |
Tugmaga hodisa ulash (addEventListener) | Observer |
PDO orqali turli bazalar bilan ishlash | Adapter |
Laravel Cache::get() fasadi | Facade |
| Ma'lumotlar bazasi ulanishi bitta bo'lishi | Singleton |
foreach ni o'z sinfingizda ishlatish | Iterator |
$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;
juftlar: 2, 4
kvadratlar: 1, 4, 9, 16, 25
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.
| Til | Strategy qanday yoziladi |
|---|---|
| Eski Java | Interfeys + sinflar (majburiy) |
| PHP 8, Python, JS | Ko'pincha oddiy funksiya yetarli |
| Haskell | Shunchaki 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:
- Bu naqsh qanday muammoni hal qiladi?
- PHP 8 da uni soddaroq yozish mumkinmi?
Bu darslikda nima bo'ladi #
| Bo'limlar | Mavzu |
|---|---|
| 1-2 | Naqsh nima, SOLID tamoyillari |
| 3-7 | Yaratuvchi naqshlar |
| 8-12 | Strukturaviy naqshlar |
| 13-18 | Xulq-atvor naqshlari |
| 19 | Naqshlarni noto'g'ri ishlatish |
| 20 | Amaliy loyiha - bir necha naqsh birga |
if/elseifzanjirli to'lov sinfini yozing.- Unga to'rtinchi usul qo'shing va nechta joyni o'zgartirganingizni sanang.
- Xuddi shu masalani interfeys bilan qayta yozing.
- Yangi usul qo'shing - endi nechta mavjud fayl o'zgardi?
- Naqsh kod miqdorini oshirdimi yoki kamaytirdimi?
- "Uch marta qoidasi" ni o'z so'zlaringiz bilan tushuntiring.
- Uch guruhni va ularning farqini yozing.
array_mapda qaysi naqsh yashiringanini ayting.- O'z kodingizdan naqshga o'xshash uchta joy toping.
- 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/elseifzanjiri 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.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.