Tervezési minták - Gyors útmutató az Observer mintájához.

A megfigyelő minta nagyon gyakran használt minta. Valójában ez olyan gyakori, hogy sok programozási nyelven / könyvtárban egységesítik. A Java-ban létezik az injava.util.Observer (a Java 9-ben elavult). Pythonban olyan közel, mint az apip install mintamegfigyelő. A C ++ programban néha használhatunk boost könyvtárat, pontosabban #include . Az iparban azonban széles körben használják egyedi gyártású megoldásként. Ahhoz, hogy helyesen tudjuk használni, és megértsük komplexitását, bele kell merülnünk és feltárnunk kell.

A megfigyelő mintát a viselkedési tervezési minták közé soroljuk. A viselkedéstervezési minták leginkább az osztályok / tárgyak közötti kommunikációra vonatkoznak. [a Design Patterns egyszerűen elmagyarázta]

Mi a megfigyelő mintája? Az egy sétáló monitoron kívül, amely analóg televíziót sugároz (mint a képen). A mintázat célja az egy-egyhez viszony meghatározása úgy, hogy amikor egy objektum megváltoztatja az állapotot, a többi értesítést kap, és automatikusan frissül. Pontosabban, tájékoztatást szeretne kapni a rendszerben zajló eseményekről. Összerakhatjuk a puzzle darabokat három lépésben.

1. lépés - Kulcsszavak

A kulcsszavak meghatározása a titkos recept ebben a gyors útmutatóban. Ez a módszer elősegítette a tervezési minták valódi megértését, a fejemben lévő kódolást és a többi tervezési minták közötti különbségek megértését.

  1. Tárgy: Az információ, az adatok vagy az üzleti logika őrzője.
  2. Regisztrálás / csatolás: A megfigyelők regisztrálják magukat a témához, mert értesülni akarnak a változásról.
  3. Esemény: Az események kiváltóként hatnak a témában, így minden megfigyelőt értesíteni kell.
  4. Értesítés: A megvalósítástól függően az alany „továbbíthatja” az információkat a megfigyelőknek, vagy a megfigyelők „elhúzhatják” a figyelmet, ha információkra van szükségük a tárgytól.
  5. Frissítés: A megfigyelők állapotát frissítik más megfigyelőktől függetlenül, azonban az állapot változhat a kiváltott eseménytől függően.

2. lépés - Diagram

Lehetővé teszi a formatervezés különféle osztályokra bontását, hogy ez kicsit egyszerűbb legyen.

  • A ConcreteObservers olyan osztályok, amelyek az aktuális példányra specifikus információkat tartalmaznak. A frissítési funkciót az alany értesítési () művelete hívja meg. A megfigyelők jelenlegi állapotuk alapján függetlenül frissülnek.
  • A Megfigyelő a konkrét megfigyelők szülőosztálya. Tárgypéldányt tartalmaz. Amikor egy megfigyelőt inicializálnak, regisztrálja / rögzíti magát a vizsgált személynél.
  • A Tárgy osztálynak van megfigyelői listája vagy gyűjteménye. Az esemény beindulásakor az értesítés () műveletet hívja meg, amely az összes megfigyelőt áthúzza azáltal, hogy meghívja a frissítési funkciót.

3. lépés - Kód példaként

Azt javaslom, hogy másolja a kódosztályt osztályonként a „Andreas Poyias” git-tárolóból vagy az alábbiakból (a megadott sorrendben), és illessze be az elérhető online C ++ szerkesztők bármelyikébe, például a c ++ shell, jdoodle, onlineGDB, és futtassa. megfigyelni a kimenetet. Ezután olvassa el az alábbi megjegyzéseket vagy leírást. Szánjon rá időt és olvassa el alaposan (ez azt jelenti, egy perc, nem kevesebb és nem több).

Példa: Vegyünk egy focimeccsen. Sok szurkoló figyeli a játékot. A támogatókat életkor szerint két kategóriába soroltuk: fiatal és idős. Amikor a csapatuk gólt szereznek, a szurkolók koruk és izgalom szintjük szerint eltérően reagálnak.
Most beszéljünk a megfigyelő mintára használt kifejezésekkel:

  • A játék a tárgy és a szurkolók a megfigyelők.
  • Minden megfigyelőt csatolnak / regisztrálnak a témához, és értesítik őket, amikor a labdarúgó-csapat gólt szerez (az esemény kiváltó eseménye, ha a csapat pontszáma).
  • A megfigyelők a kapott értesítéstől függően frissítik viselkedésüket.

Tantárgy
Ehhez az osztályhoz hozzáférnünk kell a megfigyelők listájához. Amikor a megfigyelők regisztrálni készülnek, felhívják a theattach (ezt) funkciót, hogy felvegyék magukat a rendelkezésre álló listába (ez egy megfigyelő példánya). Az esemény beindulásakor a (z) wenotify () minden megfigyelőt függetlenül frissíti az állapotával. Ebben a példában akkor kell kiváltani, ha a megfigyelő labdarúgó csapata gólt szerez.

#include 
#include 
névtér std;
osztálytárgy {
    vektor  megfigyelők;
    bool szerzett; // eseményindító
nyilvános:
    // regisztrálja a megfigyelőket
    érvénytelen csatolás (Observer * obs) {
        observers.push_back (obs);
    }
   
   // Ez az ESEMÉNY
   // állítsa be az if pontot, és értesítse az összes megfigyelőt
   void setScored (bool Score) {
      gólt = Pontszám;
      értesíti ();
   }
bool getScored () {
      visszatért pontszám;
   }
   // az implementaion értesítése lejjebb van
   // úgy, hogy a szkript összeálljon és futjon
   érvénytelen értesítés ();
};

Megfigyelő
Ez az osztály attól a tantárgytól függ, amelyen regisztrált. Amikor a konkrét megfigyelők inicializálódnak, ragaszkodnak a témahez. Ebben a példában az egyes megfigyelők állapota az ő izgalma.

osztálymegfigyelő
{
    Tárgy * subj;
    int izgalomszint; // állapot
  nyilvános:
    Megfigyelő (Tárgy * mod, int excLevel)
    {
        subj = mod;
        excitementLevel = excLevel;
        // A megfigyelők regisztrálják / csatolják magukat az alanyhoz
        subj-> csatolja (e);
    }
    virtuális érvénytelen frissítés () = 0;
  védett:
    Tárgy * getSubject () {
       visszatérés subj;
    }
    void setExcitementLevel (int excLevel) {
       excitementLevel = excLevel;
    }
    int getExcitementLevel () {
       visszatérő izgalom szint;
    }
};

Ez a TheSubject :: értesítés () nyilatkozat, és amint már korábban említettük, az a feladata, hogy értesítse az összes megfigyelőt az állapotuk frissítéséről.

érvénytelen tárgy :: értesítés () {
  mert (int i = 0; i  frissítés ();
}

Betonmegfigyelők
A konkrét megfigyelők az Observer osztálytól örökölnek, és mindegyiknek rendelkeznie kell a frissítési funkcióval. Ebben a példában a konkrét megfigyelők különbséget tesznek a fiatal és az öreg támogatók között. Ha az izgalom szintje túl magasra válik, az idősebb szurkolóknak szívroham kockázata van, a fiatalabbaknak pedig inni és vezetni kell. Állapotuk függetlenül frissül, amint azt az alábbiakban bemutatjuk a fő funkcióban.

osztály Old_ConcreteObserver: nyilvános megfigyelő
{
   nyilvános:
     // Felhívja a szülő kivitelezőt, hogy regisztráljon a tárgynál
     Old_ConcreteObserver (Tárgy * mod, int div)
        : Megfigyelő (mod, div) {}
     // Idős embereknél, ha az izgalom szintje
     // 150 felett van, szívroham kockázatát fenyegeti
     érvénytelen frissítés ()
     {
        bool score = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        if (értékelve && getExcitementLevel ()> 150)
        {
          cout << "Az Old Observer csapata gólt szerez !!"
               << "Izgalmi szintje"
               << getExcitementLevel ()
               << "vigyázz a szívrohamra!" << endl;
        }más{
          cout << "A csapat nem szerezte gólt. Yeeeihnek nem kell aggódnia"
               << endl;
        }
    } // frissítés vége ()
};
osztály Young_ConcreteObserver: nyilvános megfigyelő
{
   nyilvános:
     // Felhívja a szülő kivitelezőt, hogy regisztráljon a tárgynál
     Young_ConcreteObserver (Tárgy * mod, int div)
       : Megfigyelő (mod, div) {}
     // Idős embereknél, ha az izgalom szintje
     // 100 felett van, szívroham kockázatát jelentheti
     érvénytelen frissítés ()
     {
        bool score = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        if (értékelt && getExcitementLevel ()> 100)
        {
          cout << "A fiatal megfigyelő csapata gólt szerez !!"
               << "Izgalmi szintje"
               << getExcitementLevel ()
               << "ne igyál és vezessen !!" << endl;
        }más{
          cout << "A csapat nem szerezte gólt. Igen, semmi miatt nem kell aggódni"
               << endl;
       }
    } // frissítés vége ()
};

Fő funkció
A konkrét megfigyelők regisztrálják magukat az objektumpéldányon. Állapotuk az izgalom szintje, amely a második paraméter. Amikor az esemény „subj.setScored (true)” indul, akkor a Subject :: értesítést () hívja fel a regisztrált megfigyelők frissítésére. Az alábbi forgatókönyvben három megfigyelőnk van: a youngObs1 túlzottan túlzottan túlzottan alkoholizált, és fennáll az alkoholfogyasztás és a gépjárművezetés kockázata, a régiObs1 túlzottan túlzottan eltérő kockázatot jelent (a szívroham). Végül, a youngObs2-nek, aki szintén fiatal, mint első, nincs semmi aggódása, mivel nincs túlzottan túlsúlyban.

Fontos észrevenni, hogy a három megfigyelő állapotuk (izgalom szintje) és típusa (fiatal vagy idős) alapján függetlenül frissül.
int main () {
   Tárgy subj;
   Young_ConcreteObserver youngObs1 (& subj, 100);
   Old_ConcreteObserver oldObs1 (& subj, 150);
   Young_ConcreteObserver youngObs2 (& subj, 52);
   subj.setScored (true);
}
// Kimenet
// A Young Observer csapata gólt szerez !! Izgalmi szintje 101
// ne igyál és vezessen !!
// Az Old Observer csapata gólt szerez !! Izgalmi szintje 151 óra
// szívroham nélkül! A csapat nem gólzott.
// Igen, semmi miatt nem kell aggódnia

Néhány előnye van a Observer minta használatának, és néhány szempontot meg kell említeni, amikor ezt a mintát megközelítik [Learning Python Design Patterns].

  • A Megfigyelő mintája olyan képet ad, amelyben az alany és a Megfigyelő lazán kapcsolódik egymáshoz. A tantárgynak nem kell tudnia a ConcreteObserver osztályról. Bármely új Megfigyelő bármikor hozzáadható. Új megfigyelő hozzáadásával nem kell módosítania a Tárgyat. A megfigyelők és az alanyok nem kötődnek egymástól és függetlenek egymástól, ezért a tárgyban vagy a megfigyelőben bekövetkező változások nem érintik egymást.
  • Nincs lehetőség a kompozícióra, mivel az Observer interfész kivitelezhető.
  • Ha a Megfigyelőt visszaélik, ez könnyen összetettséggel járhat, és teljesítményproblémákhoz vezethet.
  • Az értesítések megbízhatatlanok lehetnek, és versenyfeltételeket vagy következetlenségeket eredményezhetnek.

A következő blog rövid áttekintést nyújt a Bridge tervezési mintájáról. Ez egy szerkezeti kialakítási minta, amelyet az iparban nagyon sokat használnak. Ne felejtsd el kedvelni / tapsolni a blogbejegyzésem és követni a számlám. Ez annak megelégedésére szolgál, hogy segített néhány fejlesztõ társamnak, és arra ösztönözött, hogy folytassam az írást. Ha van egy speciális tervezési minta, amelyet meg szeretne tanulni, akkor tudassa velem, hogy a jövőben ezt biztosítsam.

Egyéb tervezési minták gyors útmutatói:

  1. Tervezési minták - Rövid útmutató az absztrakt gyárhoz.
  2. Tervezési minták - A hídminták rövid útmutatója.
  3. Tervezési minták - Gyors útmutató az Építő mintákhoz.
  4. Tervezési minták - Gyors útmutató a dekorátor mintájához.
  5. Tervezési minták - A homlokzati minták rövid útmutatója.
  6. Tervezési minták - A Observer Pattern gyors útmutatója.
  7. Tervezési minták - A Singleton Pattern gyors útmutatója.