Értesítés küldés több forrásból több vevőnek – központosított üzenettovábbítás

Az előző három bejegyzésben azt a helyzetet modelleztük le programban, amikor egy szupermarket hírlevelére a vásárlók feliratkoznak azért, hogy ha új termék jelenik meg az áruház kínálatában, akkor arról értesítést kapjanak. A vásárlókat természetesen nem minden árucikk érdekeli, de ha igényük van rá, akkor is csak egy bizonyos árszint alatt hajlandóak az adott terméket megvenni.

Az előzőekben hallgatólagosan azt feltételeztük, hogy több vásárló és csak egyetlen áruház van, tehát minden vásárló ehhez az egy áruházhoz iratkozik fel. A programmodellt a megfigyelő (Observer) vagy más néven publikáló-feliratkozó (Publisher-Subscriber) tervezési minta alapján építettük fel. Ez két alapváltozatban (Push és Pull) is be lett bemutatva.

A feladatot most kibővítjük azzal az új igénnyel, hogy ne csak egy, hanem tetszőleges számú áruház lehessen, és a vásárlók bármelyikre, vagy akár az összes áruház hírlevelére feliratkozhatnak.

Ezt a feladatot is elvben meg lehet oldani az eddigi módszerrel. Azonban sok vásárló és sok áruház esetében a regisztrálások és leiratkozások kezelése nehézkessé válik. Ezért ezt a feladatot célszerű kiszervezni egy külön objektumba, aminek az a feladata, hogy a hozzá beregisztrált áruházak neki megküldött hírlevelét minden olyan potenciális vásárlónak kiküldi, akik az adott áruház hírlevelére kíváncsiak és azt jelezték. E feladatkörből adódóan ezt az új objektumot nevezhetjük üzenettovábbító központnak (messaging center).

Ha az előző bejegyzésekből kiinduló alapnak a Push változatot vesszük, akkor az új igény kielégítéséhez nem kell sokat változtatni a kódon. Alább mutatjuk azon kódokat, amelyek nem változnak a korábbihoz képest.

Itt pedig az üzenettovábbító központ objektum MessagingCenter nevű osztálydefinícióját láthatjuk:

Ennek felépítése és metódusai nagyon hasonlóak a korábban látott Publisher osztályéhoz, de tartalmi eltérésekkel. Most nem csupán a vásárlókat mint üzenetfogadókat kell nyilvántartani, hanem az üzenetküldőket is, ráadásul ezekhez eltérő vásárlók tartozhatnak. Ezért ezt egy olyan szótárban tartjuk nyilván, amelynek kulcsai az üzenetküldő áruházak, a kulcshoz tartozó értékek pedig konténerek (jelen esetben halmaz), amelyek az egyes feliratkozó vásárlók referenciáit tárolják. Értesítési kéréskor a MessagingCenter a kapott üzenetből kinyeri a küldőt, és annak ismeretében kikéri a szótárból az ehhez tartozó konténert. Ha ez megvan, akkor az abban tárolt összes feliratkozónak kiküldi az üzenetet jelentő hírlevelet. /Az áttekinthetőség kedvvért a metódusokon belül a szükséges ellenőrző kódokat mellőztük/

A MessagingCenter ismeretében már csak egy feladat marad, a Supermarket osztály módosítása ahhoz, hogy az új rendszer szerint tudjon működni és küldeni a hírleveleit az üzenettovábbító központnak. Ennek definíciója:

A korábbi bejegyzésekben szereplő osztálydefinícióhoz képesti új kódokat a 8-14 és 25-28 sorok tartalmazzák.

Láthatjuk, hogy egy új privát attribútumot vettünk fel az üzenettovábbító központ objektum nyilvántartásához. Az attribútumhoz értéket egy új, register_in_messaging_center nevű metódussal lehet adni, amennyiben az áruház szeretné igénybe venni az üzenettovábbító központ szolgáltatását. Ezek eddig kódkiterjesztések voltak. Az egyetlen valódi kódmódosítást a new_product() metódusban kell megtenni, mert most nem maga az áruház küldi ki a feliratkozóknak a hírlevelet, hanem erre a MessagingCenter példányt kell megkérni.

Vegyük észre, hogy az áruházat modellező Supermarket osztálynak most nem kell örökölnie a korábban látott Publisher osztályt, hiszen most már nem ő a felelős a vásárlók értesítéséért, ezért ilyen képességre nincs szüksége.

A rendszer működését bemutató tesztkódsorokat és azok eredményét alább követhetjük:

E bejegyzés 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ás osztá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.