Értesítés küldés állapotváltozásról – megfigyelő minta, Pull változat

Az előző két bejegyzésben egy áruház hírlevelére feliratkozó vásárlók új termék érkezéséről való tájékoztatását, és ennek alapján történő vásárlásokat modelleztük és kódoltuk a megfigyelő tervezési minta Push változata alapján.

Most ugyanezt a feladatot a megfigyelő minta Pull változatával oldjuk meg. Ahogy arról az előzőekben szó volt, a Pull változat esetén a vevő előre megkapja az áruház referenciáját és így csupán arról kell értesülnie, hogy jött valamilyen új termék, de nem szükséges a termék adatait (név, ár) megkapnia az értesítéssel együtt, mert az értesítés után ezeket maga kérdezi le az áruháztól, hiszen rendelkezik annak elérhetőségével.

A vevő két módon is megkaphatja előre az áruház referenciáját. Az egyik, hogy definiálunk számára egy feliratkozást megvalósító subscribe() metódust, aminek argumentuma az áruház hivatkozása. Ezt a metódust futás közben bármikor meghívhatjuk, és onnantól kezdve kapni fogja az értesítéseket. A másik lehetőség, hogy a példányosításkor a konstruktorban adjuk meg az áruház referenciáját. Egyszerre akár mindkét módot is biztosíthatjuk a Customer osztályban. Ezt láthatjuk alább.

Természetesen nem elegendő az __init__ módosítása és az új subscribe() metódus definiálása, hanem némi módosítást kell tenni az update() és buy() metódusokban is.

Az update() esetén, mivel most nem szükséges a message argumentum, ezért ezt opcionálissá tesszük. Azért nem töröljük, mert így a Supermarket osztály notify_subscribers() metódusa továbbra is átadhatja a hírlevelet modellező PromotionMessage példányt az update()-nek, ami azért jó, mert ha vannak Push üzemmódhoz tartozó feliratkozók, akkor ők változatlanul megkaphatják a hírleveleket.

A Customer osztályban az update() törzsében annyi változtatást kell tenni, hogy most nem a message objektumból nyerjük ki a termékadatokat, hanem – mivel a Customer példány rendelkezik az áruház referenciájával – az áruháztól kérdezzük le az új termék, azaz a new_product attribútumból a terméknevet és árat. A metódus törzs további részében pedig ezeket használjuk fel.

A buy() metódust is módosítani kell. Egyrészt az áruházat képviselő argumentumot opcionálissá tesszük. Ezt azért, hogy ha nem iratkozik fel a vásárló, akkor is tudjon vásárolni, persze csak akkor, ha az argumentumban megkapja az áruházpéldányt. A buy() metódus törzsében pedig egy feltételes elágazással eldöntjük, hogy kitől fogunk vásárolni. Ha az argumentumban megadott az áruház, akkor attól, ha pedig nem, akkor a tárolt áruházreferenciát vesszük és azon keresztül. A metódus többi kódja a Push változathoz képest nem változik.

Vegyük észre, hogy a Pull változat megvalósításához csak a Customer osztályt kellett módosítani a többit (Subscriber, Publisher, Product, PromotionMessage és Supermarket) nem, ezért ezek definícióját nem is tüntettük fel, azok az előző bejegyzésekben találhatók.

Az alább látható tesztfuttatásnál mindegyik vevőfaját bemutattuk. Két vevő a subscribe() metódusának meghívásával iratkozik fel, és egy a létrehozásakor kapja meg az áruház referenciáját. Egy további pedig feliratkozás, vagyis értesítés nélkül vásárol. A működés helyességét a kiírások mutatják.

E cikk témájához a Python tudásépítés lépésről lépésre című e-könyv következő részei kapcsolódnak: az „Osztály vigyázz! – típuslétrehozásosztályokkal” fejezet, a „Készétel fogyasztás a szabványos könyvtár moduljainak használata”  fejezet „Absztrakt osztályok” alfejezet, valamint a „Speciális konténer típusok” alfejezetén belül a „Mezőneves tuple – namedtuple” cím, az „Attribútumműveletek kontrollált végrehajtása” fejezeten belül a „Tulajdonságok létrehozása” és „Dekorátorral létrehozott tulajdonságok” alfejezetek.

Érdekel a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv.