Ontwerppatronen - Een korte handleiding voor het waarnemerspatroon.

Waarnemerspatroon is een veelgebruikt patroon. Het is zelfs zo gebruikelijk dat het in veel programmeertalen / bibliotheken wordt gestandaardiseerd. In Java bestaat het injava.util.Observer (verouderd in Java 9). In Python is het zo dichtbij als apip patroon-waarnemer installeren. In C ++ kunnen we soms een boostbibliotheek gebruiken, meer bepaald #include . Het wordt echter veel gebruikt in de industrie als een op maat gemaakte oplossing. Om het correct te kunnen gebruiken en de complexiteit ervan te begrijpen, moeten we erin duiken en het verkennen.

Waarnemerspatroon is ingedeeld bij de gedragspatronen. Gedragspatronen zijn vooral gericht op communicatie tussen klassen / objecten. [door Design Patterns eenvoudig uitgelegd]

Wat is een waarnemerspatroon? Afgezien van een wandelende monitor die analoge televisie uitzendt (zoals op de foto). Het doel van het patroon is om een ​​één-op-veel-relatie te definiëren, zodat wanneer een object van status verandert, de anderen op de hoogte worden gebracht en automatisch worden bijgewerkt. Meer in het bijzonder wil het worden geïnformeerd over gebeurtenissen in het systeem. Laten we de puzzelstukjes in drie stappen samenvoegen.

Stap 1 - Zoekwoorden

Het definiëren van trefwoorden is het geheime recept in deze serie beknopte handleidingen. Deze methode heeft me geholpen de ontwerppatronen echt te begrijpen, ze hard te coderen en de verschillen tussen andere ontwerppatronen te begrijpen.

  1. Onderwerp: het wordt beschouwd als de bewaarder van informatie, gegevens of bedrijfslogica.
  2. Registreren / bijvoegen: waarnemers registreren zichzelf bij het onderwerp omdat ze een melding willen ontvangen wanneer er een wijziging is.
  3. Gebeurtenis: gebeurtenissen fungeren als een trigger in het onderwerp, zodat alle waarnemers op de hoogte worden gebracht.
  4. Melden: Afhankelijk van de implementatie kan het onderwerp informatie naar de waarnemers "pushen", of kunnen de waarnemers "trekken" als ze informatie van het onderwerp nodig hebben.
  5. Update: waarnemers updaten hun status onafhankelijk van andere waarnemers, maar hun status kan veranderen afhankelijk van de getriggerde gebeurtenis.

Stap 2 - Diagram

Laten we dit ontwerp in verschillende klassen splitsen om dit een beetje te vereenvoudigen.

  • De ConcreteObservers zijn klassen die informatie bevatten die specifiek is voor de huidige instantie. De updatefunctie wordt aangeroepen door de kennisgeving () van de persoon. De waarnemers updaten onafhankelijk op basis van hun huidige status.
  • De waarnemer is de ouderklasse van de concrete waarnemers. Het bevat een onderwerpinstantie. Wanneer een waarnemer wordt geïnitialiseerd, registreert deze zich / hecht deze zich aan het onderwerp.
  • De klasse Onderwerp heeft een lijst of een verzameling waarnemers. Wanneer een gebeurtenis wordt geactiveerd, roept deze de melding () aan die alle waarnemers doorloopt door hun updatefunctie aan te roepen.

Stap 3 - Code per voorbeeld

Ik zou willen voorstellen om de code klasse per klasse te kopiëren uit mijn git-repository “Andreas Poyias” of de onderstaande fragmenten (in de aangegeven volgorde) en deze in een van de beschikbare online C ++ editors te plakken, zoals c ++ shell, jdoodle, onlineGDB en uitvoeren het om de uitvoer te observeren. Lees dan de opmerkingen of beschrijving hieronder. Neem de tijd om het grondig te lezen (dat betekent één minuut, niet minder en niet meer).

Voorbeeld: overweeg een voetbalspel. Veel supporters kijken naar het spel. We hebben de supporters opgedeeld in twee categorieën op leeftijd, jong en oud. Wanneer hun team een ​​doelpunt scoort, reageren de supporters anders op basis van hun leeftijd en hun opwindingsniveau.
Laten we het nu hebben over termen die worden gebruikt voor het waarnemerspatroon:

  • Het spel is het onderwerp en de supporters zijn de waarnemers.
  • Alle waarnemers zijn aan het onderwerp gehecht / geregistreerd en krijgen een melding wanneer hun voetbalteam scoort (het trigger-evenement is als hun team scoort).
  • De waarnemers updaten hun gedrag afhankelijk van de ontvangen melding.

Onderwerpen
Voor deze les hebben we toegang nodig tot een lijst van waarnemers. Wanneer de waarnemers op het punt staan ​​zich te registreren, roepen ze de functie theattach (deze) aan om zichzelf toe te voegen aan de beschikbare lijst (dit is het exemplaar van een waarnemer). Wanneer een gebeurtenis wordt geactiveerd, wenotify () alle waarnemers om onafhankelijk hun status bij te werken. In dit voorbeeld is de trigger als het voetbalteam van de waarnemer scoorde.

# include 
# include 
namespace std; gebruiken;
klasse Onderwerp {
    vector  waarnemers;
    bool scoorde; // trigger, evenement
openbaar:
    // register waarnemers
    void attach (Observer * obs) {
        observers.push_back (obs);
    }
   
   // Dit is het EVENEMENT
   // stel de if in en breng ALLE waarnemers op de hoogte
   void setScored (bool Score) {
      gescoord = Score;
      te melden ();
   }
bool getScored () {
      rendement gescoord;
   }
   // melden implementaion is verder naar beneden
   // zodat het script wordt gecompileerd en uitgevoerd
   ongeldige kennisgeving ();
};

Waarnemer
Deze klasse is afhankelijk van het onderwerp waarmee het is geregistreerd. Wanneer concrete waarnemers worden geïnitialiseerd, hechten zij zich aan het onderwerp. In dit voorbeeld is de toestand van elke waarnemer zijn opwinding over het spel.

klasse waarnemer
{
    Onderwerp * subj;
    int opwinding Niveau; // staat
  openbaar:
    Waarnemer (Onderwerp * mod, int excLevel)
    {
        subj = mod;
        excitementLevel = excLevel;
        // Waarnemers registreren / hechten zich aan het onderwerp
        subj-> attach (this);
    }
    virtuele ongeldige update () = 0;
  beschermd:
    Onderwerp * getSubject () {
       terugkeer subj;
    }
    void setExcitementLevel (int excLevel) {
       excitementLevel = excLevel;
    }
    int getExcitementLevel () {
       terugkeer opwinding Niveau;
    }
};

Dit is de verklaring :: Onderwerp () () en zoals eerder vermeld, is het zijn taak om alle waarnemers op de hoogte te brengen van hun status.

ongeldig onderwerp :: verwittigen () {
  voor (int i = 0; i  update ();
}

Concrete waarnemers
De concrete waarnemers erven van de klasse Waarnemer en ze moeten allemaal de updatefunctie hebben. In dit voorbeeld worden de concrete waarnemers onderscheiden tussen jonge en oude supporters. Als hun opwindingsniveau te hoog wordt, hebben de oudere supporters het risico op hartaanvallen en de jongere het risico op drinken en autorijden. Hun status wordt onafhankelijk bijgewerkt, zoals we hieronder in de hoofdfunctie zullen bewijzen.

class Old_ConcreteObserver: publieke waarnemer
{
   openbaar:
     // Roept de constructor van de ouder op om zich te registreren bij onderwerp
     Old_ConcreteObserver (Onderwerp * mod, int div)
        : Observer (mod, div) {}
     // Voor ouderen, als het niveau van opwinding
     // is meer dan 150 ze lopen het risico op een hartaanval
     ongeldige update ()
     {
        bool scoorde = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        if (scoorde && getExcitementLevel ()> 150)
        {
          cout << "Old Observer's team scoorde !!"
               << "Zijn niveau van opwinding is"
               << getExcitementLevel ()
               << "pas op voor hartaanvallen!" << endl;
        }anders{
          cout << "Team scoorde niet. Yeeeih niets om je zorgen over te maken"
               << endl;
        }
    } // update beëindigen ()
};
klasse Young_ConcreteObserver: publieke waarnemer
{
   openbaar:
     // Roept de constructor van de ouder op om zich te registreren bij het onderwerp
     Young_ConcreteObserver (Onderwerp * mod, int div)
       : Observer (mod, div) {}
     // Voor ouderen, als het niveau van opwinding
     // is meer dan 100 ze lopen het risico op een hartaanval
     ongeldige update ()
     {
        bool scoorde = getSubject () -> getScored ();
        setExcitementLevel (getExcitementLevel () + 1);
        if (scoorde && getExcitementLevel ()> 100)
        {
          cout << "Young Observer's team scoorde !!"
               << "Zijn niveau van opwinding is"
               << getExcitementLevel ()
               << "drink niet en rijd !!" << endl;
        }anders{
          cout << "Team scoorde niet. Je hoeft je nergens zorgen over te maken"
               << endl;
       }
    } // update beëindigen ()
};

Hoofdfunctie
De concrete waarnemers registreren zichzelf voor de Subject-instantie. Hun toestand is het opwindingsniveau dat de tweede parameter is. Wanneer de gebeurtenis "subj.setScored (true)" wordt geactiveerd, wordt Sububject :: verwittigen () opgeroepen om de geregistreerde waarnemers bij te werken. In het onderstaande scenario hebben we drie waarnemers, de youngObs1 is te opgewonden en loopt het risico van drinken en rijden, de oldObs1 wordt ook te opgewonden en loopt een ander risico (van hartaanval). Tot slot heeft youngObs2, die ook als eerste jong is, niets om zich zorgen over te maken, omdat hij niet te opgewonden is.

Het is belangrijk op te merken dat de drie waarnemers onafhankelijk zijn bijgewerkt op basis van hun status (opwindingsniveau) en hun type (jong of oud).
int main () {
   Onderwerp subj;
   Young_ConcreteObserver youngObs1 (& subj, 100);
   Old_ConcreteObserver oldObs1 (& subj, 150);
   Young_ConcreteObserver youngObs2 (& subj, 52);
   subj.setScored (true);
}
// Uitgang
// Young Observer's team scoorde !! Zijn niveau van opwinding is 101
// niet rijden en rijden !!
// Old Observer's team scoorde !! Zijn niveau van opwinding is 151 horloge
// uit hartaanvallen! Team scoorde niet.
// Yeeh niets om je zorgen over te maken

Er zijn een paar voordelen voor het gebruik van het Observer-patroon en een paar punten om op te merken wanneer dit patroon moet worden benaderd [Learning Python Design Patterns].

  • Het waarnemerspatroon biedt een ontwerp waarbij het onderwerp en de waarnemer losjes zijn gekoppeld. Het onderwerp hoeft niets te weten over de klasse ConcreteObserver. Elke nieuwe waarnemer kan op elk moment worden toegevoegd. Het is niet nodig om het onderwerp te wijzigen wanneer een nieuwe waarnemer wordt toegevoegd. Waarnemers en onderwerpen zijn niet vastgebonden en onafhankelijk van elkaar. Daarom hebben veranderingen in het onderwerp of de waarnemer geen effect op elkaar.
  • Er is geen optie voor de compositie, omdat de Observer-interface kan worden gestart.
  • Als de waarnemer misbruikt wordt, kan dit gemakkelijk complexiteit toevoegen en leiden tot prestatieproblemen.
  • Meldingen kunnen onbetrouwbaar zijn en kunnen leiden tot raceomstandigheden of inconsistentie.

De volgende blog is een korte handleiding voor het ontwerppatroon van Bridge. Het is een structureel ontwerppatroon dat vrij veel in de industrie wordt gebruikt. Vergeet niet mijn blogpost leuk te vinden / te klappen en mijn account te volgen. Dit is om mij de voldoening te geven dat ik sommige mede-ontwikkelaars heb geholpen en me aanspoort om te blijven schrijven. Als er een specifiek ontwerppatroon is waarover u meer wilt weten, laat het me dan weten zodat ik het u in de toekomst kan bieden.

Andere snelgidsen over ontwerppatronen:

  1. Design Patterns - Een korte handleiding voor Abstract Factory.
  2. Design Patterns - Een korte handleiding voor Bridge Pattern.
  3. Design Patterns - Een korte handleiding voor Builder Pattern.
  4. Design Patterns - Een korte handleiding voor Decorator Pattern.
  5. Ontwerppatronen - Een korte handleiding voor gevelpatroon.
  6. Ontwerppatronen - Een korte handleiding voor het waarnemerspatroon.
  7. Design Patterns - Een korte handleiding voor Singleton Pattern.