Oblike oblikovanja - Hitri vodnik po vzorcu Opazovalca.

Vzorec opazovalcev je zelo pogosto uporabljen vzorec. Pravzaprav je tako pogost, da je standardiziran v mnogih programskih jezikih / knjižnicah. V Javi obstaja injava.util.Observer (zastarelo v Javi 9). V Python-u je tako blizu kot apip namestite vzorec opazovalca. V C ++ lahko včasih uporabimo boost knjižnico, natančneje #include . Vendar se v industriji pogosto uporablja kot rešitev po meri. Da ga bomo znali pravilno uporabljati in razumeti njegovo kompleksnost, se moramo potapljati in raziskati.

Vzorec opazovalcev je razvrščen med vzorce vedenjskega oblikovanja. Vzorec vedenjskega oblikovanja se še posebej ukvarja s komunikacijo med razredi / predmeti. [z obrazložitvijo oblikovalskih vzorcev preprosto]

Kaj je vzorec opazovalcev? Razen sprehajalnega monitorja, ki oddaja analogno televizijo (kot na sliki). Cilj vzorca je določiti razmerje med mnogimi, tako da ko se en predmet spremeni stanje, se drugi obvesti in posodobi samodejno. Natančneje, želi biti obveščen o dogodkih v sistemu. Naj sestavljajo koščke sestavljanke v treh korakih.

1. korak - Ključne besede

Določitev ključnih besed je skrivni recept v tej seriji hitrih vodnikov. Ta metoda mi je pomagala resnično razumeti oblikovalske vzorce, jih trdo kodirati in razumeti razlike med drugimi oblikovalskimi vzorci.

  1. Zadeva: Šteje se za hrambo informacij, podatkov ali poslovne logike.
  2. Registracija / priloga: Opazovalci se prijavijo na zadevo, ker želijo biti obveščeni, ko pride do spremembe.
  3. Dogodek: Dogodki delujejo kot sprožilec teme, tako da so vsi opazovalci obveščeni.
  4. Obveščajte: Odvisno od izvedbe lahko subjekt informacije "potisne" na opazovalce ali pa jih lahko "potegnejo", če od njega potrebujejo informacije.
  5. Posodobitev: Opazovalci posodobijo svoje stanje neodvisno od drugih opazovalcev, vendar se njihovo stanje lahko spremeni, odvisno od sproženega dogodka.

2. korak - diagram

Razdelimo to zasnovo na različne razrede, da to nekoliko poenostavimo.

  • ConcreteObservers so razredi, ki vsebujejo informacije, specifične za trenutni primerek. Funkcijo posodabljanja pokliče zadeva operacija notify (). Opazovalci se posodabljajo neodvisno glede na trenutno stanje.
  • Opazovalec je matični razred konkretnih opazovalcev. Vsebuje predmetni primerek. Ko se opazovalec inicializira, se registrira / pritrdi na zadevo.
  • Predmetni razred ima seznam ali zbirko opazovalcev. Ko se dogodek sproži, pokliče operacijo notify (), ki prekriva vse opazovalce, tako da pokliče njihovo funkcijo posodabljanja.

3. korak - kodirajte z zgledom

Predlagam, da kopirate kodo po razredu iz svojega git repozitorija "Andreas Poyias" ali spodnjih odrezkov (v vrstnem redu) in ga prilepite v katerega koli od razpoložljivih spletnih urejevalnikov C ++, kot so c ++ shell, jdoodle, onlineGDB in zaženite da opazuje izhod. Nato preberite komentarje ali opis spodaj. Vzemite si čas in ga temeljito preberite (to pomeni eno minuto, ne manj in ne več).

Primer: razmislite o nogometni tekmi. Številni podporniki si ogledajo tekmo. Podpornike razdelimo v dve kategoriji po starosti, mladi in stari. Ko njihova ekipa doseže zadetek, se navijači odzivajo drugače glede na starost in stopnjo navdušenja.
Zdaj pa se pogovorimo z izrazi, ki se uporabljajo za vzorec opazovanja:

  • Igra je tema in podporniki so opazovalci.
  • Vsi opazovalci so priloženi / registrirani na zadevo in so obveščeni, ko njihova nogometna ekipa zadene (sprožilni dogodek je, če njihova ekipa doseže rezultat).
  • Opazovalci posodobijo svoje vedenje glede na prejeto obvestilo.

Predmet
Za ta razred potrebujemo dostop do seznama opazovalcev. Ko se bodo opazovalci registrirali, pokličejo funkcijo theattach (to), da se dodajo na seznam, ki je na voljo (to je opazovalni primer). Ko se dogodek sproži, povabite () vse opazovalce, da neodvisno posodobijo svoje stanje. V tem primeru je sprožilec, če je opazovalčeva nogometna ekipa zadela.

#include 
#include 
z uporabo imenskega prostora std;
Predmet razreda {
    vektor ;
    bool rezultat; // sprožilec, dogodek
javno:
    // registrirajte opazovalce
    razveljavitev (Observer * obs) {
        opazovalec.push_back (obs);
    }
   
   // To je DOGODEK
   // nastavite vrednost if in obvestite VSE opazovalce
   void setScored (ocena bool) {
      dosežen = rezultat;
      obvestiti();
   }
bool getScored () {
      povratna ocena;
   }
   // izvedba obveščanja je nadalje omejena
   // tako, da se skript zbere in zažene
   nično obvestilo ();
};

Opazovalec
Ta razred je odvisen od predmeta, s katerim je registriran. Ko se konkretni opazovalci inicializirajo, se pritrdijo na predmet. V tem primeru je stanje vsakega opazovalca njegovo navdušenje.

razred Opazovalec
{
    Predmet * subj;
    int navdušenjeLevel; // država
  javno:
    Opazovalec (Subject * mod, int excLevel)
    {
        subj = mod;
        excitementLevel = excLevel;
        // Opazovalci se registrirajo / priložijo s Predmetom
        subj-> pritrditi (to);
    }
    navidezna posodobitev ničnosti () = 0;
  zaščiteno:
    Predmet * getSubject () {
       vrniti subj;
    }
    void setExcitementLevel (int excLevel) {
       excitementLevel = excLevel;
    }
    int getExcitementLevel () {
       povratno navdušenjeLevel;
    }
};

To je izjavaSubject :: notify () in kot smo že omenili, je njena naloga opozoriti vse opazovalce, naj posodobijo svoje stanje.

void Subject :: obvesti (() {
  za (int i = 0; i  posodobitev ();
}

Konkretni opazovalci
Konkretni opazovalci dedujejo od razreda Observer in vsi morajo imeti funkcijo posodabljanja. V tem primeru se konkretni opazovalci ločijo med mladimi in starimi podporniki. Če njihova stopnja navdušenja postane previsoka, imajo starejši navijači tveganje za srčni infarkt, mlajši pa tveganje za pijačo in vožnjo. Njihovo stanje se posodablja neodvisno, kot bomo pokazali v glavni funkciji v nadaljevanju.

razred Old_ConcreteObserver: javni opazovalec
{
   javno:
     // Pokliče nadrejeni konstruktor, da se registrira z zadevo
     Old_ConcreteObserver (Subject * mod, int div)
        : Opazovalec (mod, div) {}
     // Za starejše, če je razburjenje
     // je več kot 150, tvegajo srčni infarkt
     neveljavna posodobitev ()
     {
        bool ocena = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        če (doseženo && getExcitementLevel ()> 150)
        {
          cout << "Ekipa starega opazovalca je zadela !!"
               << "Njegova stopnja navdušenja je"
               << getExcitementLevel ()
               << "pazi na srčni napad!" << endl;
        } else {
          cout << "Ekipa ni dosegla zadetka. Yeeeih nič skrbeti"
               << endl;
        }
    } // končaj posodobitev ()
};
razred Young_ConcreteObserver: javni opazovalec
{
   javno:
     // Pokliče nadrejeni konstruktor, da se registrira z zadevo
     Young_ConcreteObserver (Predmet * mod, int div)
       : Opazovalec (mod, div) {}
     // Za starejše, če je razburjenje
     // je več kot 100, tvegajo srčni infarkt
     neveljavna posodobitev ()
     {
        bool ocena = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        če (doseženo && getExcitementLevel ()> 100)
        {
          cout << "Ekipa mladega opazovalca je zadela !!"
               << "Njegova stopnja navdušenja je"
               << getExcitementLevel ()
               << "ne pijem in ne voziš !!" << endl;
        } else {
          cout << "Ekipa ni dosegla zadetka.
               << endl;
       }
    } // končaj posodobitev ()
};

Glavna funkcija
Konkretni opazovalci se prijavijo na primer predmeta. Njihovo stanje je stopnja vznemirjenja, ki je drugi parameter. Ko se dogodek sproži “subj.setScored (true)”, potem pokličeSubject :: notify (), da posodobi registrirane opazovalce. V spodnjem scenariju imamo tri opazovalce. YoungObs1 je prekomerno razburjen in tvega, da pijete in vozite, stari Obs1 je tudi pretirano navdušen. Končno, mladiObs2, ki je prav tako mlad kot prvi, nima česa skrbeti, saj ni pretirano navdušen.

Pomembno je opozoriti, da so se trije opazovalci posodobili neodvisno glede na stanje (vznemirjenost) in vrsto (mladi ali stari).
int main () {
   Predmet subj;
   Young_ConcreteObserver youngObs1 (& subj, 100);
   Old_ConcreteObserver oldObs1 (& subj, 150);
   Young_ConcreteObserver youngObs2 (& subj, 52);
   subj.setScored (resnično);
}
// Izhod
// Ekipa mladega opazovalca je zadela !! Njegova stopnja navdušenja je 101
// ne pijem in vozim !!
// Ekipa Old Observer je zadela !! Njegova stopnja navdušenja je 151 ur
// izven srčnih napadov! Ekipa ni dosegla zadetka.
// Yeeh nič skrbeti

Nekaj ​​prednosti pri uporabi vzorca Observer in nekaj točk, ki jih je treba upoštevati pri približevanju tega vzorca [Učenje Python Design Patterns].

  • Vzorec opazovalca ponuja zasnovo, pri kateri sta zadeva in opazovalec ohlapno povezana. Predmetu ni treba vedeti o razredu ConcreteObserver. Vsak nov opazovalec je lahko dodan kadar koli. Ko dodate novega Opazovalca, teme ni treba spreminjati. Opazovalci in subjekti niso povezani in so neodvisni drug od drugega, zato spremembe v Predmetu ali Opazovalcu ne bodo vplivale druga na drugo.
  • Za sestavo ni možnosti, saj je mogoče opazovalni vmesnik opazovati.
  • Če se opazovalec zlorabi, lahko preprosto doda zapletenost in privede do težav z uspešnostjo.
  • Obvestila so lahko nezanesljiva in lahko vodijo do dirkaških razmer ali neskladnosti.

Naslednji blog bo hiter vodnik po vzorcu oblikovanja mostu. Gre za strukturni vzorec oblikovanja, ki se v industriji precej uporablja. Ne pozabite všečkati / zapoditi moje objave v blogu in spremljati moj račun. To mi bo dalo zadovoljstvo, da sem pomagal nekaterim kolegom razvijalcem in me spodbudil k nadaljevanju pisanja. Če obstaja poseben oblikovalski vzorec, o katerem bi se radi pozanimali, mi to sporočite, da vam ga lahko dam v prihodnosti.

Druga hitra navodila o oblikovalskih vzorcih:

  1. Oblike oblikovanja - hiter vodnik po tovarni Abstrakt.
  2. Oblike oblikovanja - Hitri vodnik po vzorcu mostu.
  3. Oblike oblikovanja - Hitri vodnik za vzorec Builderja.
  4. Oblikovalski vzorci - Hitri vodnik o vzorcu Dekorater.
  5. Oblike oblikovanja - Hitri vodnik po vzorcu fasade.
  6. Oblike oblikovanja - Hitri vodnik po vzorcu opazovalcev.
  7. Oblike oblikovanja - Hitri vodnik za Singleton Pattern.