IlmHamroh
Python kursi/Arxitektura5/12-dars17 daqiqa
Mundarija (22)

27.5-dars: Dizayn naqshlari — xulq-atvor (behavioral)

27-QISM — ARXITEKTURA · 5-dars


1. Kirish va motivatsiya

Obyektlar yaratildi 27.3-bob, bog'landi 27.4-bob — endi ular bir-biri bilan ishlashi kerak: kim kimni chaqiradi, mas'uliyat qanday taqsimlanadi, algoritm qanday tanlanadi, o'zgarish qanday xabar qilinadi. Buni chalkash yozsangiz — obyektlar bir-biriga qattiq bog'lanadi (if/elif daraxti, to'g'ridan chaqiruvlar), o'zgarish qiyin bo'ladi. Xulq-atvor naqshlari — obyektlar qanday o'zaro ishlashi va mas'uliyat taqsimlashi haqidagi sinalgan yechimlar: algoritmni almashtiriladigan qiladi, o'zgarishni xabar qiladi, so'rovni o'raydi.

Xulq-atvor naqshlari (behavioral patterns) — obyektlar orasidagi muloqot va mas'uliyat ni tartibga soladi: Strategy (strategiya — algoritmni almashtiriladigan qilish), Observer (kuzatuvchi — o'zgarishni obunachilarga xabar qilish), Command (buyruq — amalni obyektga o'rash), Iterator (iterator — to'plamni ketma-ket aylanish), State (holat — holatga qarab xulq o'zgarishi). Bu naqshlar if/elif ni polimorfizmga aylantiradi, qattiq bog'lanishni ajratadi (Observer), xulqni moslashuvchan qiladi. Ular SOLID ni 27.2-bob qo'llaydi: OCP (yangi strategiya), DIP (abstraksiya). Xulq-atvor naqshlari — obyektlar raqsining koreografiyasi.

Real vaziyat. Bir loyihada narx hisoblash if mijoz == "oddiy": ... elif mijoz == "vip": ... elif mijoz == "ulgurji": ... — yangi turdagi mijoz qo'shilsa, shu blok o'sardi. Strategy naqshi qo'llanildi: har chegirma turi alohida sinf (OddiyChegirma, VipChegirma), narx strategiya.hisobla(summa) chaqiradi. Yangi tur — yangi sinf (if tegilmaydi). Kod ochiq va toza bo'ldi. Strategy — algoritmni tanlanadigan qildi.

Bu darsda xulq-atvor dizayn naqshlarini o'rganamiz.

Bu darsda:

  • Xulq-atvor naqsh nima
  • Strategy (strategiya)
  • Observer (kuzatuvchi)
  • Command (buyruq)
  • Iterator (iterator)
  • State (holat)
  • Xulq-atvor naqshlari va moslashuvchanlik
  • Amaliy: naqsh qo'llash

ℹ Misollar sof Python bilan — deterministik.


2. Nazariya — chuqur tushuntirish

2.1. Xulq-atvor naqsh nima

Obyektlar o'zaro ishlashi:

Obyektlar → kim kimni chaqiradi, mas'uliyat taqsimi
Xulq-atvor: algoritm, xabar, buyruq, aylanish, holat
Muloqotni moslashuvchan qilish (qattiq bog'lanmasdan)

Xulq-atvor naqsh — obyektlar orasidagi muloqot va mas'uliyat taqsimoti haqidagi sinalgan yechim: kim kimni chaqiradi, algoritm qanday tanlanadi, o'zgarish qanday tarqaladi. Yaratuvchi 27.3-bob obyekt tug'ilishini, strukturaviy 27.4-bob bog'lanishini, xulq-atvor — o'zaro ishlashini boshqaradi. Maqsad: muloqotni moslashuvchan (qattiq bog'lanmasdan), xulqni almashtiriladigan qilish. Foydali: ko'p algoritm (Strategy), o'zgarish xabari (Observer), amal tarixi (Command). Xulq-atvor naqsh — obyektlar hamkorligi.

2.2. Strategy (strategiya)

Algoritmni almashtiriladigan qilish:

python
# har algoritm alohida sinf
class OddiyChegirma:
    def hisobla(self, summa): return summa
class VipChegirma:
    def hisobla(self, summa): return summa * 0.8

class Savat:
    def __init__(self, strategiya): self.strategiya = strategiya
    def yakuniy(self, summa): return self.strategiya.hisobla(summa)

Strategy (strategiya) — bir vazifaning turli algoritmlarini alohida sinflar qilib, ish vaqtida almashtiriladigan qiladi: Savat chegirma strategiyasini oladi (OddiyChegirma, VipChegirma), strategiya.hisobla() chaqiradi. Sabab: bir vazifa (chegirma, saralash, to'lov) ko'p usulda bajariladi — if/elif o'rniga polimorfizm (OCP: yangi usul = yangi sinf). Mijoz strategiyani tanlaydi (yoki almashtiradi). Foydalanish: chegirma, saralash, siqish, to'lov usuli. Strategy — algoritmni tanlanadigan qilish (if/elif o'rniga).

2.3. Observer (kuzatuvchi)

O'zgarishni obunachilarga xabar:

python
class Manba:
    def __init__(self): self.kuzatuvchilar = []
    def obuna(self, k): self.kuzatuvchilar.append(k)
    def xabar(self, hodisa):
        for k in self.kuzatuvchilar: k.yangilanish(hodisa)
# manba o'zgardi → barcha obunachi xabar oladi

Observer (kuzatuvchi) — bir obyekt (manba) o'zgarganda, unga obuna bo'lgan obyektlarni (kuzatuvchilar) avtomatik xabardor qiladi: manba.xabar() — barcha kuzatuvchiga yangilanish(). Sabab: bir o'zgarishga ko'p javob (bir hodisa — ko'p reaksiya) — manba javob beruvchilarni bilmasligi kerak (past bog'liqlik). Nashr-obuna (pub-sub) modeli. Foydalanish: hodisa tizimi (event), UI yangilanish, xabarnoma, jurnal. Observer — bir o'zgarish, ko'p xabar (ajratilgan). Manba obunachini bilmaydi — faqat xabar qiladi.

2.4. Command (buyruq)

Amalni obyektga o'rash:

python
class Buyruq:
    def bajar(self): ...
    def bekor(self): ...
class YoqishBuyrugi(Buyruq):
    def __init__(self, chiroq): self.chiroq = chiroq
    def bajar(self): self.chiroq.yoq()
    def bekor(self): self.chiroq.ochir()
# buyruq — obyekt (saqlash, navbat, bekor qilish)

Command (buyruq) — amalni (nima qilish) obyektga o'raydi: bajar() metodli obyekt (parametrlari bilan). Sabab: amal obyekt bo'lsa — uni saqlash (tarix), navbatga qo'yish (kechiktirilgan), bekor qilish (bekor() — undo), qayta bajarish (redo) mumkin. Chaqiruvchi amalni bilmaydi (faqat bajar()). Foydalanish: undo/redo, navbat, tranzaksiya, makro, tugma amali. Command — amalni obyektlashtirish (saqlanadigan, bekor qilinadigan). Amal — obyekt (birinchi sinf).

2.5. Iterator (iterator)

To'plamni ketma-ket aylanish:

python
class Toplam:
    def __init__(self, elementlar): self.elementlar = elementlar
    def __iter__(self): return iter(self.elementlar)
# for x in toplam: ... (ichki tuzilmani bilmasdan)

Iterator (iterator) — to'plam elementlarini ketma-ket aylanish usulini (ichki tuzilmani ochmasdan) beradi: __iter__, __next__ (Python'da tabiiy — for bilan). Sabab: to'plamni aylanish uning ichki tuzilmasidan (ro'yxat, daraxt, grafik) mustaqil bo'lishi kerak (mijoz for x in toplam yozadi, ichini bilmaydi). Python bunga qurilgan (__iter__, generator — 13-qism). Foydalanish: har qanday to'plam, oqim, cheksiz ketma-ketlik (generator). Iterator — aylanishni tuzilmadan ajratish. Python'da iterator — til qismi.

2.6. State (holat)

Holatga qarab xulq o'zgarishi:

python
# obyekt xulqi holatiga qarab o'zgaradi
class Buyurtma:
    def __init__(self): self.holat = "yangi"
    def keyingi(self):
        if self.holat == "yangi": self.holat = "tolangan"
        elif self.holat == "tolangan": self.holat = "yuborilgan"
# holat mashinasi (state machine)

State (holat) — obyekt xulqi uning ichki holatiga qarab o'zgaradi (go'yo sinf o'zgargandek): buyurtma "yangi" → "to'langan" → "yuborilgan" — har holatda amallar boshqacha. Murakkab holatlarda har holat alohida sinf (YangiHolat, TolanganHolat) — holatga qarab xulq (if holat o'rniga polimorfizm). Sabab: holatga bog'liq murakkab xulq (holat mashinasi — state machine) — ravshan, kengaytiriladigan. Foydalanish: buyurtma oqimi, o'yin holati, ulanish, hujjat holati. State — holatga qarab xulq (holat mashinasi).

2.7. Xulq-atvor naqshlari va moslashuvchanlik

Xulq-atvor naqshlari moslashuvchanlikni oshiradi: Strategy algoritmni (almashtiriladigan), Observer javoblarni (qo'shiladigan), Command amallarni (saqlanadigan, bekor), State xulqni (holatga qarab), Iterator aylanishni (tuzilmadan mustaqil). Umumiy g'oya: if/elif daraxtlari va qattiq chaqiruvlarni polimorfizm va ajratilgan muloqot ga aylantirish (OCP — yangi xulq qo'shish, mavjudni o'zgartirmasdan). Ular obyektlarga javobgarlikni aniq taqsimlaydi (kim nimani qiladi). Xulq-atvor naqshlari — xulqni moslashuvchan qilish. Polimorfizm — if/elif ning yechimi.

2.8. Xulq-atvor naqshlari — tizim dinamikasi

Xulq-atvor naqshlari tizimning dinamikasini (ish vaqtidagi harakat) shakllantiradi: yaratuvchi va strukturaviy — statik (tuzilma), xulq-atvor — dinamik (o'zaro ishlash, oqim). Katta tizimda (hodisaga asoslangan — 27.10, CQRS — 27.11) bu naqshlar asosiy: Observer (hodisa, pub-sub), Command (buyruq, CQRS), State (holat mashinasi, ish oqimi). Ular yaratuvchi 27.3-bob va strukturaviy 27.4-bob ustiga quriladi: obyekt tug'iladi, bog'lanadi, keyin harakatga keladi. Uch naqsh turi birga to'liq tizim: yaratish + bog'lash + xulq. Xulq-atvor naqshlari — tizim jonli qismi (harakat). Dinamika — tizim yashaydi.


3. Tez ma'lumotnoma

python
# STRATEGY — almashtiriladigan algoritm
class AlgoritmA: def bajar(self, x): return x * 2
class Kontekst:
    def __init__(self, strategiya): self.s = strategiya
    def ishla(self, x): return self.s.bajar(x)

# OBSERVER — o'zgarish xabari
class Manba:
    def __init__(self): self.kuzatuvchilar = []
    def xabar(self, h):
        for k in self.kuzatuvchilar: k.yangilanish(h)

# COMMAND — amal obyekti
class Buyruq:
    def bajar(self): ...
    def bekor(self): ...

# ITERATOR — aylanish
class Toplam:
    def __iter__(self): return iter(self.elementlar)

# STATE — holatga qarab xulq
class Kontekst:
    def keyingi(self): self.holat = self.holat.keyingi()

Xulq-atvor naqshlari xulosasi

Strategy — almashtiriladigan algoritm (if/elif o'rniga)
Observer — o'zgarish xabari (pub-sub, ajratilgan)
Command — amal obyekti (saqlash, bekor, navbat)
Iterator — aylanish (tuzilmadan mustaqil, Python __iter__)
State — holatga qarab xulq (holat mashinasi)
Maqsad: moslashuvchanlik (polimorfizm, OCP)

4. Batafsil misollar

Misollar sof Python bilan — deterministik.

Misol 1 — Strategy: almashtiriladigan chegirma

python
"""Strategy: turli chegirma algoritmlari alohida sinf (if/elif o'rniga)."""
from abc import ABC, abstractmethod


class ChegirmaStrategiyasi(ABC):
    @abstractmethod
    def hisobla(self, summa: float) -> float: ...


class OddiyMijoz(ChegirmaStrategiyasi):
    def hisobla(self, summa: float) -> float:
        return summa


class VipMijoz(ChegirmaStrategiyasi):
    def hisobla(self, summa: float) -> float:
        return summa * 0.8   # 20% chegirma


class UlgurjiMijoz(ChegirmaStrategiyasi):
    def hisobla(self, summa: float) -> float:
        return summa * 0.7   # 30% chegirma


class Savat:
    def __init__(self, strategiya: ChegirmaStrategiyasi) -> None:
        self.strategiya = strategiya

    def yakuniy_narx(self, summa: float) -> float:
        return self.strategiya.hisobla(summa)


def main() -> None:
    print("=== 1. Oddiy mijoz ===")
    print(f"  1000 → {Savat(OddiyMijoz()).yakuniy_narx(1000)}")

    print("\n=== 2. VIP mijoz ===")
    print(f"  1000 → {Savat(VipMijoz()).yakuniy_narx(1000)}")

    print("\n=== 3. Ulgurji mijoz ===")
    print(f"  1000 → {Savat(UlgurjiMijoz()).yakuniy_narx(1000)}")

    print("\n=== 4. Strategiyani almashtirish ===")
    savat = Savat(OddiyMijoz())
    print(f"  oddiy: {savat.yakuniy_narx(500)}")
    savat.strategiya = VipMijoz()   # ish vaqtida almashtirish
    print(f"  VIP ga o'tdi: {savat.yakuniy_narx(500)}")
    print("  yangi tur = yangi sinf (if/elif yo'q)")
    print("  ⭐ Strategy — almashtiriladigan algoritm")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Oddiy mijoz ===
  1000 → 1000

=== 2. VIP mijoz ===
  1000 → 800.0

=== 3. Ulgurji mijoz ===
  1000 → 700.0

=== 4. Strategiyani almashtirish ===
  oddiy: 500
  VIP ga o'tdi: 400.0
  yangi tur = yangi sinf (if/elif yo'q)
  ⭐ Strategy — almashtiriladigan algoritm

Nima ko'rsatdi: 2.2-bo'lim.

Misol 2 — Observer: o'zgarish xabari

python
"""Observer: manba o'zgarganda barcha obunachiga xabar (pub-sub)."""
from abc import ABC, abstractmethod


class Kuzatuvchi(ABC):
    @abstractmethod
    def yangilanish(self, narx: float) -> str: ...


class Xaridor(Kuzatuvchi):
    def __init__(self, ism: str) -> None:
        self.ism = ism

    def yangilanish(self, narx: float) -> str:
        return f"{self.ism}: yangi narx {narx}"


class NarxManbasi:
    def __init__(self) -> None:
        self.kuzatuvchilar: list = []
        self._narx = 0.0

    def obuna(self, k: Kuzatuvchi) -> None:
        self.kuzatuvchilar.append(k)

    def narx_ornat(self, narx: float) -> list:
        self._narx = narx
        # barcha obunachiga xabar
        return [k.yangilanish(narx) for k in self.kuzatuvchilar]


def main() -> None:
    manba = NarxManbasi()

    print("=== 1. Obunachilar qo'shish ===")
    manba.obuna(Xaridor("Ali"))
    manba.obuna(Xaridor("Vali"))
    print(f"  obunachilar soni: {len(manba.kuzatuvchilar)}")

    print("\n=== 2. Narx o'zgardi → xabar ===")
    for xabar in manba.narx_ornat(100):
        print(f"  {xabar}")

    print("\n=== 3. Yana o'zgardi ===")
    for xabar in manba.narx_ornat(90):
        print(f"  {xabar}")

    print("\n=== 4. Yangi obunachi ===")
    manba.obuna(Xaridor("Guli"))
    print(f"  jami xabar oluvchi: {len(manba.narx_ornat(80))}")
    print("  manba obunachini bilmaydi (ajratilgan)")
    print("  ⭐ Observer — bir o'zgarish, ko'p xabar")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Obunachilar qo'shish ===
  obunachilar soni: 2

=== 2. Narx o'zgardi → xabar ===
  Ali: yangi narx 100
  Vali: yangi narx 100

=== 3. Yana o'zgardi ===
  Ali: yangi narx 90
  Vali: yangi narx 90

=== 4. Yangi obunachi ===
  jami xabar oluvchi: 3
  manba obunachini bilmaydi (ajratilgan)
  ⭐ Observer — bir o'zgarish, ko'p xabar

Nima ko'rsatdi: 2.3-bo'lim.

Misol 3 — Command: bekor qilinadigan amal

python
"""Command: amalni obyektga o'rash — bajar/bekor (undo) va tarix."""
from abc import ABC, abstractmethod


class Buyruq(ABC):
    @abstractmethod
    def bajar(self) -> str: ...

    @abstractmethod
    def bekor(self) -> str: ...


class Hisob:
    def __init__(self) -> None:
        self.balans = 0


class QoshishBuyrugi(Buyruq):
    def __init__(self, hisob: Hisob, miqdor: int) -> None:
        self.hisob = hisob
        self.miqdor = miqdor

    def bajar(self) -> str:
        self.hisob.balans += self.miqdor
        return f"+{self.miqdor} → {self.hisob.balans}"

    def bekor(self) -> str:
        self.hisob.balans -= self.miqdor
        return f"bekor -{self.miqdor} → {self.hisob.balans}"


class Boshqaruvchi:
    def __init__(self) -> None:
        self.tarix: list = []

    def ishga_tushir(self, buyruq: Buyruq) -> str:
        natija = buyruq.bajar()
        self.tarix.append(buyruq)
        return natija

    def orqaga(self) -> str:
        if self.tarix:
            return self.tarix.pop().bekor()
        return "tarix bo'sh"


def main() -> None:
    hisob = Hisob()
    boshqaruvchi = Boshqaruvchi()

    print("=== 1. Buyruqlarni bajarish ===")
    print(f"  {boshqaruvchi.ishga_tushir(QoshishBuyrugi(hisob, 100))}")
    print(f"  {boshqaruvchi.ishga_tushir(QoshishBuyrugi(hisob, 50))}")

    print("\n=== 2. Tarix ===")
    print(f"  bajarilgan buyruqlar: {len(boshqaruvchi.tarix)}")

    print("\n=== 3. Orqaga (undo) ===")
    print(f"  {boshqaruvchi.orqaga()}")
    print(f"  {boshqaruvchi.orqaga()}")

    print("\n=== 4. Bo'sh tarix ===")
    print(f"  {boshqaruvchi.orqaga()}")
    print("  amal — obyekt (saqlash, bekor qilish)")
    print("  ⭐ Command — amalni obyektlashtirish")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Buyruqlarni bajarish ===
  +100 → 100
  +50 → 150

=== 2. Tarix ===
  bajarilgan buyruqlar: 2

=== 3. Orqaga (undo) ===
  bekor -50 → 100
  bekor -100 → 0

=== 4. Bo'sh tarix ===
  tarix bo'sh
  amal — obyekt (saqlash, bekor qilish)
  ⭐ Command — amalni obyektlashtirish

Nima ko'rsatdi: 2.4-bo'lim.

Misol 4 — State: holat mashinasi

python
"""State: buyurtma xulqi holatiga qarab o'zgaradi (holat mashinasi)."""


class Buyurtma:
    OQIM = {
        "yangi": "tolangan",
        "tolangan": "yuborilgan",
        "yuborilgan": "yetkazilgan",
        "yetkazilgan": None,
    }

    def __init__(self) -> None:
        self.holat = "yangi"

    def keyingi(self) -> str:
        keyingi_holat = self.OQIM.get(self.holat)
        if keyingi_holat is None:
            return f"{self.holat}: oxirgi holat (o'zgarmaydi)"
        eski = self.holat
        self.holat = keyingi_holat
        return f"{eski} → {self.holat}"

    def bekor_qilsa_boladimi(self) -> bool:
        # faqat 'yangi' va 'tolangan' bekor qilinadi
        return self.holat in ("yangi", "tolangan")


def main() -> None:
    b = Buyurtma()

    print("=== 1. Boshlang'ich holat ===")
    print(f"  holat: {b.holat}")
    print(f"  bekor qilsa bo'ladimi: {b.bekor_qilsa_boladimi()}")

    print("\n=== 2. Holat o'tishlari ===")
    print(f"  {b.keyingi()}")
    print(f"  {b.keyingi()}")

    print("\n=== 3. Holatga qarab xulq ===")
    print(f"  hozir '{b.holat}' — bekor: {b.bekor_qilsa_boladimi()}")

    print("\n=== 4. Oxirigacha ===")
    print(f"  {b.keyingi()}")
    print(f"  {b.keyingi()}")   # oxirgi
    print("  har holatda xulq boshqacha (holat mashinasi)")
    print("  ⭐ State — holatga qarab xulq")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Boshlang'ich holat ===
  holat: yangi
  bekor qilsa bo'ladimi: True

=== 2. Holat o'tishlari ===
  yangi → tolangan
  tolangan → yuborilgan

=== 3. Holatga qarab xulq ===
  hozir 'yuborilgan' — bekor: False

=== 4. Oxirigacha ===
  yuborilgan → yetkazilgan
  yetkazilgan: oxirgi holat (o'zgarmaydi)
  har holatda xulq boshqacha (holat mashinasi)
  ⭐ State — holatga qarab xulq

Nima ko'rsatdi: 2.6-bo'lim.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"if/elif yetadi" Strategy (polimorfizm)
"Manba javobchini biladi" Observer (ajratilgan)
"Amal — funksiya" Command (obyekt, bekor)
"Iterator murakkab" Python __iter__ (tabiiy)
"Holat = o'zgaruvchi" State (holat mashinasi)
"Naqsh doim kerak" Muammo bo'lganda
"Xulq statik" Almashtiriladigan (dinamik)
"Bir javob yetadi" Observer (ko'p javob)

6. Keng tarqalgan xatolar va yechimlari

1. if/elif algoritm daraxti

python
if tur=="a": ... elif tur=="b": ...   # o'sadi  # ⚠️
class StrategiyaA: def bajar(self)              # ✅

2. Observer — qattiq bog'lanish

python
manba.xaridor1.yangila()  # aniq              # ⚠️
for k in kuzatuvchilar: k.yangilanish()       # ✅

3. Command — bekorni unutish

python
class Buyruq: def bajar(self)   # undo yo'q    # ⚠️
def bajar(self): ...; def bekor(self): ...     # ✅

4. Iterator — Python idiomini e'tiborsiz

python
def get_all(self): return self.items          # ⚠️
def __iter__(self): return iter(self.items)    # ✅

5. State — ulkan if daraxti

python
if holat=="a": ... elif ...   # murakkab       # ⚠️
# holat sinflar yoki OQIM lug'ati              # ✅

6. Observer — xato bir kuzatuvchini to'xtatadi

python
for k in kuzatuvchilar: k.yangila()  # xato → to'xtash  # ⚠️
try: k.yangila() except: log()  # davom etadi           # ✅

7. Naqshni majburlash

python
# oddiy funksiyaga Strategy sinf              # ⚠️
# oddiy — funksiya; ko'p algoritm — Strategy   # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 27.3–27.4-dars (o'tilgan): Yaratuvchi, strukturaviy
  • 27.10-dars: Hodisaga asoslangan — Observer
  • 27.11-dars: CQRS — Command
  • 27.2-dars (o'tilgan): SOLID — OCP, DIP
  • 13-qism (o'tilgan): Iteratorlar, generatorlar

8. Eng yaxshi amaliyotlar

  1. Strategy — algoritm daraxtini polimorfizmga.

  2. Observer — manba javobchini bilmasin.

  3. Command — bekor (undo) qo'sh.

  4. Iterator — __iter__ (Python idiomi).

  5. State — holat mashinasi (if daraxti emas).

  6. Observer — xatoni izolyatsiya qil.

  7. Naqsh — muammoga (majburlama).

  8. Oddiy funksiya — oddiy holatga.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # xulq-atvor naqsh nima?
2.  # Strategy nima?
3.  # Strategy nima uchun?
4.  # Observer nima?
5.  # pub-sub nima?
6.  # Command nima?
7.  # Command foyda (undo)?
8.  # Iterator nima?
9.  # Python iterator?
10. # State nima?
11. # holat mashinasi nima?
12. # naqsh maqsadi?
Javoblar
  1. Obyektlar o'zaro ishlashi naqshlari
  2. Almashtiriladigan algoritm
  3. if/elif o'rniga (OCP)
  4. O'zgarishni obunachiga xabar
  5. Nashr-obuna (manba-kuzatuvchi)
  6. Amalni obyektga o'rash
  7. Saqlash, bekor (undo), navbat
  8. To'plamni aylanish
  9. __iter__, generator
  10. Holatga qarab xulq
  11. State machine (holat o'tishlari)
  12. Moslashuvchanlik (polimorfizm)

Vazifa 2: Xatolarni tuzating

python
1.  if tur=="a" elif tur=="b"      # Strategy

2.  manba.xaridor1.yangila()       # ro'yxat

3.  class Buyruq: bajar (undosiz)   # bekor

4.  def get_all(self)              # __iter__

5.  if holat=="a" elif ...          # holat mashinasi
Javoblar
python
1.  class StrategiyaA: def bajar(self)

2.  for k in kuzatuvchilar: k.yangilanish()

3.  def bajar(self); def bekor(self)

4.  def __iter__(self): return iter(...)

5.  OQIM lug'ati yoki holat sinflar

Vazifa 3: Strategy

Tuzing:

  1. Interfeys
  2. Algoritmlar
  3. Kontekst
  4. Almashtirish

Vazifa 4: Observer

Tuzing:

  1. Manba
  2. Kuzatuvchi
  3. Obuna
  4. Xabar

Vazifa 5: Command

Tuzing:

  1. Buyruq
  2. bajar
  3. bekor
  4. Tarix

Vazifa 6: State

Tuzing:

  1. Holatlar
  2. O'tish
  3. Xulq
  4. Mashina

Vazifa 7: O'ylash

Xulq-atvor naqshlarining ko'pi (Strategy, State) if/elif daraxtlarini polimorfizm ga aylantiradi. Nima uchun katta if/elif (yoki switch) daraxtlari "kod hidi" (code smell — muammo belgisi) hisoblanadi, va nega polimorfizm (har holat/tur alohida sinf) uni yechadi — lekin qachon oddiy if yaxshiroq (polimorfizmdan)?

Javob

Qisqa javob: Katta if/elif daraxtlari "kod hidi", chunki: ular o'sadi (yangi tur = yangi shox — bir joyda to'planadi, uzayadi), takrorlanadi (bir xil if tur == ... daraxti ko'p joyda — narx, ko'rinish, tekshirish), OCP ni buzadi (yangi tur qo'shish = mavjud kodni o'zgartirish — xato xavfi), SRP ni buzadi (bir funksiya barcha turlarni biladi — ko'p mas'uliyat). Polimorfizm buni yechadi, chunki: har tur/holat alohida sinf (bir joyda bir turning barcha xulqi) — yangi tur = yangi sinf (mavjud tegilmaydi — OCP), if yo'qoladi (obyekt.metod() — polimorfizm turni "biladi"). Lekin polimorfizm doim yaxshiroq emas: oddiy if yaxshiroq, qachonki — kam holat (2-3, o'zgarmaydigan — masalan if x > 0), oddiy shart (mantiqiy, tur emas), bir joyda (takrorlanmaydi), mahalliy (kichik funksiya ichida). Polimorfizm narx: yangi sinflar (ko'proq fayl, abstraksiya), sakrash (kodni o'qishda sinfdan sinfga) — kam holatga bu ortiqcha (KISS buzildi). Qoida: if qiymat (raqam, shart) uchun yaxshi, tur/holat (kengayadigan) uchun polimorfizm. "Hid" — if turga qarab tarmoqlanadi va o'sadi/takrorlanadi; oddiy mantiqiy if — hid emas. Muhandislik saboqlari: har if yomon emas (mantiq kerak); yomon — turga qarab tarmoqlanuvchi, o'suvchi, takrorlanuvchi if (polimorfizm o'rnini bosishi kerak); tajriba farqni ajratadi (qiymat sharti vs tur tarmog'i); polimorfizm ham narx (kam holatga ortiqcha) — muvozanat.

1. Nega if/elif daraxti — hid

  • O'sadi (yangi tur = yangi shox)
  • Takrorlanadi (bir daraxt ko'p joyda)
  • OCP buzadi (yangi tur = o'zgartirish)
  • SRP buzadi (bir funksiya barcha tur)

2. Polimorfizm qanday yechadi

Har tur = alohida sinf. Yangi tur = yangi sinf (OCP). if yo'qoladi (obyekt turni biladi).

3. Qachon oddiy if yaxshiroq

Holat Tanlov
Kam, o'zgarmas, mantiqiy shart if
Ko'p, kengayadigan, turga qarab Polimorfizm

4. Polimorfizm narxi

Yangi sinflar, abstraksiya, sakrash (o'qishda). Kam holatga ortiqcha (KISS).

5. Muhandislik saboqlari

  1. Har if yomon emas (mantiq kerak)
  2. Yomon — turga qarab, o'suvchi, takrorlanuvchi if
  3. if qiymatga, polimorfizm turga
  4. Polimorfizm ham narx (muvozanat)

6. Xulosa

  1. if/elif daraxti o'sadi, takrorlanadi (hid)
  2. Polimorfizm — har tur alohida (OCP)
  3. Oddiy if — kam, mantiqiy shart uchun
  4. Muvozanat (qiymat vs tur, narx)

Nimani mustahkamlaydi: 2.2, 2.6-bo'limlar.


Xulosa

Bu darsda xulq-atvor dizayn naqshlarini o'rgandik.

Eng muhim uch fikr:

  1. Xulq-atvor naqsh, Strategy, Observer. Xulq-atvor naqsh — obyektlar orasidagi muloqot va mas'uliyat taqsimoti yechimi (kim kimni chaqiradi, algoritm qanday tanlanadi, o'zgarish qanday tarqaladi); yaratuvchi (tug'ilish) va strukturaviy (bog'lanish) dan keyin — o'zaro ishlash. Strategy (strategiya) — turli algoritmlarni alohida sinf qilib, ish vaqtida almashtiriladigan qiladi (if/elif o'rniga polimorfizm — OCP: yangi usul = yangi sinf); chegirma, saralash, to'lov. Observer (kuzatuvchi) — manba o'zgarganda obuna bo'lganlarga avtomatik xabar (pub-sub); manba javob beruvchini bilmaydi (past bog'liqlik); hodisa, UI, xabarnoma.

  2. Command, Iterator, State. Command (buyruq) — amalni obyektga o'raydi (bajar(), bekor()); amal obyekt bo'lsa — saqlash (tarix), navbat, bekor (undo), qayta bajarish (redo); undo/redo, tranzaksiya, makro. Iterator (iterator) — to'plamni ketma-ket aylanish (ichki tuzilmani ochmasdan); Python'da tabiiy (__iter__, generator — 13-qism), aylanishni tuzilmadan ajratadi. State (holat) — obyekt xulqi ichki holatiga qarab o'zgaradi (buyurtma: yangi → to'langan → yuborilgan); murakkab holatlarda har holat alohida sinf (holat mashinasi — state machine, if holat o'rniga polimorfizm).

  3. Moslashuvchanlik va tizim dinamikasi. Xulq-atvor naqshlari if/elif daraxtlari va qattiq chaqiruvlarni polimorfizm va ajratilgan muloqot ga aylantiradi (OCP — yangi xulq, mavjudni o'zgartirmasdan) va javobgarlikni aniq taqsimlaydi. Katta if/elif daraxti — "kod hidi" (o'sadi, takrorlanadi, OCP/SRP buzadi); polimorfizm yechadi (har tur alohida sinf), lekin oddiy if yaxshiroq — kam, o'zgarmas, mantiqiy shart uchun (if qiymatga, polimorfizm turga; polimorfizm ham narx — muvozanat). Xulq-atvor naqshlari tizim dinamikasini (ish vaqtidagi harakat) shakllantiradi: yaratuvchi/strukturaviy — statik (tuzilma), xulq-atvor — dinamik (o'zaro ishlash); hodisaga asoslangan (27.10 — Observer), CQRS (27.11 — Command), holat mashinalari (State) uchun asos. Uch naqsh turi birga to'liq tizim: yaratish + bog'lash + xulq — tizim jonli qismi (harakat).

Keyingi darsda qatlamli arxitekturani o'rganamiz: tizimni mas'uliyatga qarab qatlamlarga (taqdimot, biznes mantiq, ma'lumot) bo'lish — har qatlam o'z vazifasi, aniq chegaralar va bir yo'nalishli bog'liqlik bilan.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!