Tarkkailija (suunnittelukuvio)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 19. toukokuuta 2019 tarkistetusta versiosta . tarkastukset vaativat 15 muokkausta .
Tarkkailija
Tarkkailija
Tyyppi käyttäytymiseen
Tarkoitus
  • Observer-malli määrittää objektien välisen riippuvuuden yksi-moneen siten, että kun yhden objektin tila muuttuu, kaikki objektit, jotka ovat riippuvaisia ​​siitä, ilmoitetaan ja päivitetään automaattisesti;
  • Observer-malli kapseloi pääkomponentin (riippumattoman) Subject-abstraktion ja muuttuvat (riippuvaiset) komponentit Observer-hierarkiassa;
  • Observer-kuvio määrittelee "View"-osan Model-View-Controller (MVC) -mallissa [1] .
Kuvattu suunnittelukuvioissa Joo

Observer on käyttäytymissuunnittelumalli . _  _ _ _ Tunnetaan myös nimellä "alaiset" ( eng. Dependents ). Toteuttaa luokkamekanismin, jonka avulla tämän luokan objekti voi vastaanottaa ilmoituksia muiden objektien tilan muutoksista ja siten tarkkailla niitä [2] .  

Luokkia, joiden tapahtumia muut luokat tilaavat, kutsutaan aiheiksi ja tilaajaluokkia kutsutaan Observeriksi [ 3 ] . 

Samankaltaiset mallit: " julkaisija-tilaaja ", " välittäjä ", " yksinäinen ".

Tapaaminen

Määrittää objektien välisen riippuvuuden yksi useaan siten, että kun yhden objektin tila muuttuu, kaikki siitä riippuvaiset saavat ilmoituksen tapahtumasta.

Toteutus

Toteutettaessa tarkkailijamallia käytetään yleisesti seuraavia luokkia:

Laajuus

Tarkkailijakuviota käytetään, kun järjestelmällä on seuraavat ominaisuudet:

Tätä mallia käytetään usein tilanteissa, joissa viestien lähettäjä ei ole kiinnostunut siitä, mitä vastaanottajat tekevät heille toimitetuilla tiedoilla.

Esimerkkejä

PHP5 (SPL)

Lähdeteksti php-kielellä /** * PHP tarjoaa sisäänrakennetun tuen tälle mallille mukana tulevan * SPL (Standard PHP Library) -laajennuksen kautta: * SplObserver - käyttöliittymä Observerille (observer), * SplSubject - Observable (havaittavissa), * SplObjectStorage - apuluokka (tarjoaa parannetun *-objektien tallentamisen ja poistamisen , erityisesti attach()- ja detach()-menetelmät ovat käytössä). */ luokka Havaittava toteuttaa SplSubject { yksityinen $tallennustila ; function __construct () { $this -> storage = new SplObjectStorage (); } function liitä ( SplObserver $observer ) { $this -> varastointi -> liitä ( $observer ); } function detach ( SplObserver $observer ) { $this -> storage -> detach ( $observer ); } function notify () { foreach ( $this -> storage as $obj ) { $obj -> päivitys ( $this ); } } } luokka ConcreteObserver toteuttaa SplObserverin { yksityinen $havaittava ; yksityinen $indeksi ; function __construct ( Havaittava $havaittava ) { staattinen $sindex = 0 ; $this -> index = $sindex ++ ; $this -> havaittava = $havaittava ; $havaittavissa -> liitä ( $this ); } funktion päivitys ( SplSubject $subject ) { if ( $subject === $this -> observable ) { echo "Lähetä ilmoitus ConcreteObserverille [ $this->index ] \n " ; } } } $havaittava = uusi Havaittava (); uusi ConcreteObserver ( $havaittava ); uusi ConcreteObserver ( $havaittava ); uusi ConcreteObserver ( $havaittava ); $havaittavissa -> ilmoittaa ();

PHP5

Lähdeteksti php-kielellä käyttöliittymä Observer { function notify ( $obj ); } class Vaihtokurssi { staattinen yksityinen $instanssi = NULL ; yksityinen $tarkkailijat = array (); yksityinen $vaihtokurssi ; yksityinen funktio __construct () {} yksityinen funktio __klooni () {} staattinen julkinen funktio getInstance () { if ( itse :: $instanssi == NULL ) { itse :: $instanssi = uusi Vaihtokurssi (); } return self :: $instance ; } public function getExchangeRate () { return $this -> vaihtokurssi ; } public function setExchangeRate ( $uusi_kurssi ) { $this -> vaihtokurssi = $uusi_kurssi ; $this -> notifyObservers (); } julkinen toimintorekisteriObserver ( Observer $obj ) { $this -> tarkkailijat [] = $ obj ; } function notifyObservers () { foreach ( $this -> tarkkailijat kuten $obj ) { $obj -> notify ( $this ); } } } luokka ProductItem toteuttaa Observer { public function __construct () { ExchangeRate :: getInstance () -> registerObserver ( $this ); } public function notify ( $obj ) { if ( $obj instanceof ExchangeRate ) { // Päivitä valuuttakurssitiedot print "Päivitys vastaanotettu! \n " ; } } } $tuote1 = uusi tuotenimike (); $tuote2 = uusi tuotenimike (); ExchangeRate :: getInstance () -> setExchangeRate ( 4.5 );

C#

Lähdeteksti C# käyttäen System ; käyttämällä System.Collections -ohjelmaa ; käyttäen System.Collections.Generic ; käyttäen System.Threading ; nimiavaruus Observer { /// <yhteenveto> /// Observer Pattern Judith Bishop tammikuu 2007 /// Päivittänyt Kobel' Bohdan 2013 /// /// Aihe toimii säikeessä ja muuttaa tilaansa /// itsenäisesti. Jokaisesta muutoksesta se ilmoittaa tarkkailijoilleen. /// </summary> class Ohjelma { static void Main ( string [] args ) { Subject topic = new Subject (); Observer tarkkailija = uusi Tarkkailija ( aihe , "Keski" , "\t\t" ); Observer tarkkailija2 = uusi Tarkkailija ( aihe , "Oikea" , "\t\t\t\t" ); aihe . mene (); // Odota käyttäjän konsolia . lue (); } } luokan simulaattori : IEnumerable { merkkijono [] liikkuu = { "5" , "3" , "1" , "6" , "7" }; public IEnumerator GetEnumerator ( ) { foreach ( merkkijonoelementti siirroissa ) tuotto return element ; _ } } käyttöliittymä ISubject { void AddObserver ( IObserver- tarkkailija ); void RemoveObserver ( IObserver- tarkkailija ); void NotifyObservers ( merkkijono s ); } class Subject : ISubject { julkinen merkkijono SubjectState { get ; asettaa ; } julkinen lista < IObserver > Tarkkailijat { get ; yksityinen sarja ; } yksityinen Simulaattorisimulaattori ; _ yksityinen const int nopeus = 200 ; public Subject () { Tarkkailijat = new List < IObserver >(); simulaattori = uusi Simulaattori (); } public void AddObserver ( IObserver - tarkkailija ) { Tarkkailijat . Lisää ( tarkkailija ); } public void RemoveObserver ( IObserver - tarkkailija ) { Tarkkailijat . Poista ( tarkkailija ); } public void NotifyObservers ( merkkijonot ) { foreach ( var tarkkailija Observersissa ) { tarkkailija . _ _ Päivitys ( t ); } } public void Mene () { uusi säie ( uusi ketjun aloitus ( Suorita )). Aloita ( ); } void Suorita ( ) { foreach ( merkkijono simulaattorissa ) { Konsoli . _ WriteLine ( "Aihe: " + s ); SubjectState = s ; NotifyObservers ( t ); lanka . nukkua ( nopeus ); // millisekuntia } } } käyttöliittymä IObserver { void Päivitys ( merkkijonon tila ); } class Observer : IObserver { merkkijonon nimi ; ISaihe aihe ; merkkijonon tila ; merkkijono rako ; public Observer ( ISubject - aihe , merkkijonon nimi , merkkijonoväli ) { this . aihe = aihe ; tämä . nimi = nimi ; tämä . aukko = aukko ; aihe . AddObserver ( tämä ); } public void Päivitys ( merkkijono subjectState ) { state = subjectState ; konsoli . WriteLine ( aukko + nimi + ": " + tila ); } } }

Java

Java lähde // Esimerkki kuvaa kuinka vastaanottaa tietoja sääasemalta (WeatherData-luokka, tapahtumanvälittäjä) ja //käyttää sitä sen näyttämiseen näytöllä (CurrentConditionsDisplay-luokka, tapahtumakuuntelija). //Kuuntelija rekisteröidään havainnoijaan registerObserver-menetelmällä (tässä tapauksessa kuuntelija lisätään tarkkailijaluetteloon). //Rekisteröityminen tapahtuu, kun currentDisplay-objekti luodaan, koska rakentajassa käytetään registerObserver-menetelmää. //Kun säätiedot muuttuvat, kutsutaan notifyObservers-metodia, joka puolestaan ​​kutsuu päivitysmenetelmän //kaikille kuuntelijoille ja välittää heille päivitetyt tiedot. tuonti java.util.LinkedList ; tuonti java.util.List ; public class WeatherStation { public static void main ( String [] args ) { WeatherData weatherData = new WeatherData (); Observer currentDisplay = new CurrentConditionsDisplay (); säätiedot . registerObserver ( currentDisplay ); säätiedot . setMeasurements ( 29 f , 65 f , 745 ); säätiedot . setMeasurements ( 39 f , 70 f , 760 ); säätiedot . setMeasurements ( 42 f , 72 f , 763 ); } } käyttöliittymä Observer { void update ( kelluvan lämpötila , kelluntakosteus , sisäpaine ) ; _ } käyttöliittymä Observable { void registerObserver ( Observer o ); void removeObserver ( Observer o ); mitätön notifyObservers (); } luokka WeatherData toteuttaa Observable { yksityinen luettelo < Observer > tarkkailijat ; yksityinen kelluva lämpötila ; yksityinen kelluva kosteus ; yksityinen sisäinen paine ; public WeatherData () { tarkkailijat = new LinkedList <> (); } @Override public void registerObserver ( Observer o ) { tarkkailijat . lisää ( o ); } @Override public void removeObserver ( Observer o ) { tarkkailijat . poista ( o ); } @Override public void notifyObservers () { for ( Observer tarkkailija : tarkkailijat ) tarkkailija . päivitys ( lämpötila , kosteus , paine ); } public void setMittaukset ( kelluvan lämpötila , kellukkeen kosteus , sisäpaine ) { this . _ lämpötila = lämpötila ; tämä . kosteus = kosteus ; tämä . paine = paine ; notifyObservers (); } } class CurrentConditionsNäyttö toteuttaa Observer { yksityinen kelluva lämpötila ; yksityinen kelluva kosteus ; yksityinen sisäinen paine ; @Override public void päivitys ( kelluvan lämpötila , kelluntakosteus , sisäpaine ) { this . _ _ lämpötila = lämpötila ; tämä . kosteus = kosteus ; tämä . paine = paine ; näyttö (); } public void display () { Järjestelmä . ulos . printf ( "Nyt arvot ovat: %.1f celsiusastetta ja %.1f %% kosteus. Paine %d mmHg\n" , lämpötila , kosteus , paine ); } }

C++

Lähdeteksti C++:ssa #include <iostream> #sisällytä <merkkijono> #include <list> käyttäen nimiavaruutta std ; luokka SupervisedString ; luokan IObserver { julkinen : virtuaalinen void handleEvent ( const ValvottuString & ) = 0 ; }; class SupervisedString // Havaittava luokka { merkkijono_str ; _ lista < IObserver *> _observers ; void _Notify () { for ( auto & tarkkailija : _observers ) { tarkkailija -> handleEvent ( * this ); } } julkinen : tyhjä lisäys ( IObserver & ref ) { _tarkkailijat . push_back ( & ref ); } void remove ( IObserver & ref ) { _tarkkailijat . poista ( & ref ); } const merkkijono & get () const { return_str ; _ } void reset ( string str ) { _str = str ; _Ilmoita (); } }; class Reflector : public IObserver // Tulostaa havaitun merkkijonon muotoon cout { julkinen : virtuaalinen void handleEvent ( const SupervisedString & ref ) { cout << ref . get () << endl ; } }; class Counter : public IObserver // Tulostaa havaitun merkkijonon pituuden arvoon cout { julkinen : virtuaalinen void handleEvent ( const SupervisedString & ref ) { cout << "length = " << ref . saada (). pituus () << endl ; } }; int main () { ValvottuString str ; heijastin refl ; Counter cnt ; str . lisää ( refl ); str . reset ( "Hei, maailma!" ); cout << endl ; str . poistaa ( refl ); str . lisää ( cnt ); str . nollaa ( "Maailma, hei!" ); cout << endl ; paluu 0 ; }

ActionScript

Lähdeteksti ActionScriptissä //tiedosto IObserver.as paketti { julkinen käyttöliittymä IObserver { function notify ( obj : Object ): void ; } } //tiedosto ExchangeRate.as paketti { public class Vaihtokurssi { yksityinen staattinen var _instance : Vaihtokurssi = null ; yksityiset var tarkkailijat : Array = []; yksityinen var _exchangeRate : Objekti ; public function ExchangeRate () { if ( _instance == null ) throw new Error ( 'Model Singleton!' ); } julkinen staattinen funktio getInstance (): Vaihtokurssi { if ( _instance == null ) _instance = new ExchangeRate (); return _instance ; } julkinen toiminto saada vaihtokurssi (): Object { return _exchangeRate ; } julkinen funktiojoukko ExchangeRate ( arvo : Object ) : void { _vaihtonopeus = arvo ; tämä . notifyObservers (); } public function registerObserver ( arvo : IObserver ): void { this . tarkkailijat . push ( arvo ); } yksityinen toiminto notifyObservers ( ) : void { jokaiselle ( var tarkkailija : IObserver tässä . tarkkailijat ) { tarkkailija . ilmoittaa ( tämä ); } } } } //tiedosto ProductItem.as paketti { public class ProductItem toteuttaa IObserverin { public function ProductItem () { Vaihtokurssi . getInstance (). registerObserver ( tämä ); } julkinen toiminto notify ( arvo : Object ) : void { if ( arvo on Vaihtokurssi ) { var Exchange : Vaihtokurssi = arvo vaihtokurssina ; jäljittää ( Exchange.exchangeRate ) ; _ } } } } //tiedosto Main.as package { import flash.display.Sprite ; public class Main extends Sprite { public function Main (): void { var item1 : ProductItem = new ProductItem (); var item2 : ProductItem = uusi tuotetuote (); Valuuttakurssi . getInstance (). vaihtokurssi = 3,5 ; } } }

VB.NET

Lähdeteksti VB.NET-kielellä Tuo System.Collections Tuo System.Threading Nimiavaruus Observer ''' <yhteenveto> ''' Observer Pattern Judith Bishop tammi 2007 ''' ''' Aihe kulkee säikeessä ja muuttaa tilaa '''' itsenäisesti. Jokaisesta muutoksesta se ilmoittaa tarkkailijoilleen. '''' </summary> Luokka Ohjelma Jaettu Sub Main () Himmeä aihe uutena aiheena () Himmeä tarkkailija uutena tarkkailijana ( aihe , " Keski " , vbTab & vbTab ) Himmeä tarkkailija2 uutena tarkkailijana ( aihe , " oikea " , vbTab & vbTab & vbTab & vbTab ) aihe . mene () Odota käyttäjäkonsolia . Lue () End Sub loppuluokka _ Luokkasimulaattori toteuttaa IEnumerable yksityisiä siirtoja merkkijonona ( ) = { " 5" , "3" , "1" , "6" , "7" } Julkinen funktio GetEnumerator () Kuten IEnumerator toteuttaa IEnumerable . GetEnumerator Return liikkeet . GetEnumerator ' // Tuoton loppufunktion loppuluokka Luokan aiheen julkisen edustajan alisoitto ( ByVal s As String ) _ Julkinen tapahtuma Ilmoita takaisinsoittona Yksityinen simulaattori uutena simulaattorina ( ) Yksityinen m_SubjectState merkkijonona Yksityinen Const nopeus kokonaislukuna = 200 _ _ _ Julkinen omaisuus SubjectState ( ) Merkkijonona Hae palautus m_SubjectState Loppu Hanki Set ( ByVal arvo merkkijonona ) m_SubjectState = arvo Loppujoukko Lopeta ominaisuus _ _ Julkinen Sub Go () Call ( Uusi säie ( Uusi ketjun aloitus ( AddressOf Run ))). Aloita () Loppu Sub Yksityinen Sub Run ( ) Jokaiselle s String In Simulator Console . _ WriteLine ( "Aihe: " & s ) SubjectState = s RaiseEvent Notify ( s ) ' millisekuntia Thread . Sleep ( nopeus ) Next End Sub End Class Interface IObserver Sub Update ( ByVal tila merkkijonona ) End Interface _ Class Observer toteuttaa IObserverin Yksityinen nimi Merkkijonona Yksityinen aihe Aiheena Yksityinen tila Merkkijonona Yksityinen aukko Merkkijonona _ _ _ _ Julkinen Sub Uusi ( ByVal - aihe Aiheena , ByVal nimi Merkkijonona , ByVal aukko merkkijonona ) Me . _ _ aihe = aihe minä . nimi = nimi minä . aukko = aukko AddHandler - aihe . Ilmoita , AddressOf Update End Sub Julkinen alipäivitys ( ByVal subjectState As String ) Toteuttaa IObserverin . _ Päivitä tila = subjectStateConsole . _ WriteLine ( aukko & nimi & ": " & tila ) End Sub End Class End Namespace

Python

Lähdekoodi Pythonissa abc importista ABCMeta , abstrakti menetelmä luokan tarkkailija ( metaluokka = ABCMeta ): """ Abstrakti tarkkailija """ @abstractmethod def update ( self , message : str ) -> Ei mitään : """ Hanki uusi viesti """ pass luokka Havaittavissa ( metaluokka = ABCMeta ): """ Abstrakti havaittava """ def __init__ ( itse ) -> Ei mitään : """ Rakentaja. """ itse . tarkkailijat = [] # tarkkailijaluettelon alustaminen def register ( itse , tarkkailija : Tarkkailija ) -> Ei mitään : """ Rekisteröi uusi tarkkailija tilataksesi """ itsensä . tarkkailijat . liittää ( tarkkailija ) def notify_observers ( self , message : str ) -> None : """ Lähetä viesti kaikille havainnoijille, jotka ovat tilaaneet tietyn objektin tapahtumiin havainnoitavissa olevan luokan " "" havainnoijalle itsestään . tarkkailijat : tarkkailija . päivitys ( viesti ) luokan Sanomalehti ( Havaittavissa ): """ Sanomalehti, jota seuraa tuhansia ihmisiä """ def add_news ( self , news : str ) -> Ei mitään : """ Uusi uutistiedote """ self . notify_observers ( uutiset ) luokan kansalainen ( Tarkkailija ): """ Tavallinen kansalainen, joka tykkää lukea lempilehtiään aamulla """ def __init__ ( itse , nimi : str ) -> Ei mitään : """ Rakentaja. :param nimi: kansalaisen nimi , jotta häntä ei sekoitettaisi johonkin toiseen """ itse .nimi = nimi def update ( self , message : str ) -> Ei mitään : """ Haetaan seuraava uutinen """ print ( f ' { self . name } oppi seuraavaa: { viesti } ' ) if __name__ == '__main__' : newspaper = Sanomalehti () # luo pieni sanomalehti . rekisteröidy ( Kansalainen ( 'Ivan' )) # lisää kaksi sanomalehteä . rekisteröidy ( Kansalainen ( 'Vasily' )) # ... se on säännöllisesti tilattu # ... ja heitämme toisen sanomalehden ankkalehden . add_news ( 'Observer - Behavioral Design Pattern' ) ''' Ivan oppi seuraavaa: Tarkkailija - käyttäytymissuunnittelumalli Vasily oppi seuraavaa: Tarkkailija - käyttäytymissuunnittelumalli '''

ObjectPascal

Lähdeteksti Object Pascalissa (Delphi) ohjelman tarkkailija ; /// Observer Pattern Judith Bishop tammikuu 2007 /// Siirtynyt Pascaliin Dmitry Boyarintsev, toukokuu 2018 /// /// Aihe kulkee säikeessä ja muuttaa tilaa /// itsenäisesti. Jokaisesta muutoksesta se ilmoittaa tarkkailijoilleen. {$ifdef fpc}{$mode delphi}{$H+}{$endif} käyttää SysUtils , Classes ; tyyppi TBaseObserver = luokka ( TObject ) - menettely Päivitys ( const astate : merkkijono ) ; virtuaalinen ; abstrakti ; loppu ; TBaseSubject = luokka ( TObject ) - menettely AddObserver ( aobserver : TBaseObserver ) ; virtuaalinen ; abstrakti ; menettely RemoveObserver ( aobserver : TBaseObserver ) ; virtuaalinen ; abstrakti ; menettely NotifyObservers ( const s : string ) ; virtuaalinen ; abstrakti ; loppu ; tyyppi { TSubject } TSubject = luokka ( TBaseSubject ) yksityiset fObservers : TList ; fSimulaattori : TStringList ; nopeus : Kokonaisluku ; suojattu menettely Suorita ; julkinen rakentaja Luo ; tuhoaja Tuhoa ; ohittaa ; menettely AddObserver ( aobserver : TBaseObserver ) ; ohittaa ; menettely RemoveObserver ( aobserver : TBaseObserver ) ; ohittaa ; menettely NotifyObservers ( const astate : string ) ; ohittaa ; menettely Mene ; loppu ; TObserver = luokka ( TBaseObserver ) yksityinen fnimi : merkkijono ; fsubject : TBaseSubject ; fstate : merkkijono _ fgap : merkkijono _ julkinen konstruktori Luo ( asubject : TBaseSubject ; const aname , agap : merkkijono ) ; menettely Päivitys ( const astate : string ) ; ohittaa ; loppu ; { TSubject } menettely TSubject . juosta ; var i : kokonaisluku ; s : merkkijono _ aloita i : = 0 : sta fSimulatoriin . Count - 1 do begin s := fSimulaattori [ i ] ; Writeln ( 'Aihe: ' , s ) ; NotifyObservers ( t ) ; uni ( nopeus ) ; // millisekunnin loppu ; loppu ; rakentaja TSubject . luoda ; alkaa peritty Luo ; fObservers := TList . luoda ; nopeus := 200 ; fSimulator := TStringList . luoda ; fSimulaattori . AddStrings ([ '5' , '3' , '1' , '6' , '7' ]) ; loppu ; destructor TSubject . Tuhoa ; aloita fObservers . Ilmainen ; fSimulaattori . Ilmainen ; loppu ; menettely TSubject . AddObserver ( aobserver : TBaseObserver ) ; aloita fObservers . Lisää ( aobserver ) ; loppu ; menettely TSubject . RemoveObserver ( aobserver : TBaseObserver ) ; aloita fObservers . Poista ( aobserver ) ; loppu ; menettely TSubject . NotifyObservers ( const astate : string ) ; var i : kokonaisluku ; aloita i := 0 : lle fObservers . Count - 1 do TBaseObserver ( fObservers [ i ]) . Päivitys ( astate ) ; loppu ; tyyppi { TMethodThread } TMethodThread = luokka ( TThread ) suojattu fMethod : TThreadMethod ; menettely Suorita ; ohittaa ; julkinen konstruktori Luo ( AMethod : TThreadMethod ) ; loppu ; { TMethodThread } rakentaja TMethodThread . Luo ( AMethod : TThreadMethod ) ; begin fMethod := AMethod ; FreeOnTerminate := True ; peritty Luo ( false ) ; loppu ; menettely TMethodThread . Suorita ; aloita jos Assigned ( fMethod ) then fMethod ( ) ; loppu ; menettely TSubject . mene ; aloita TMethodThread . Luo ( Self.Run ) ; _ _ loppu ; rakentaja TObserver . Luo ( asubject : TBaseSubject ; const aname , agap : merkkijono ) ; alkaa peritty Luo ; fsubject := asubject ; fname := aname ; fgap := agap ; jos Assigned ( fsubject ) niin fsubject . AddObserver ( itse ) ; loppu ; menettely TObserver . Päivitä ( const astate : string ) ; begin fstate := astate ; writeln ( fgap , fname , ':' , tila ) ; loppu ; /// Pääohjelma var aihe : TSubject ; tarkkailija : TObserver ; tarkkailija2 : TObserver ; beginsubject : = TSubject . luoda ; tarkkailija := TObserver . Luo ( aihe , 'keskus' , #9#9 ) ; tarkkailija2 := TObserver . Luo ( aihe , 'Oikea' , #9#9#9#9 ) ; kokeile aihetta . mene () ; // Odota käyttäjää readln ; vihdoinkin tarkkailija . Ilmainen ; tarkkailija2 . Ilmainen ; aihe . Ilmainen ; loppu ; loppua .

Ruby

Rubyn lähdekoodi moduuli Havaittava def alusta @observers = [] loppu def add_observer ( tarkkailija ) @observers << tarkkailija ellei @observers . sisältää? ( tarkkailija ) loppu def delete_observer ( tarkkailija ) @observers . poista ( tarkkailija ) loppu def notify_observers @observers . jokainen { | x | x . päivitys ( itse )} end end luokka Työntekijät ovat Havaittavissa attr_reader :name attr_accessor :title , :salary def alustaa ( nimi , titteli , palkka ) super ( ) @ nimi = nimi @ nimi = nimike @ palkka = palkka loppu loppu luokka BaseObserver def update nosta 'On toteutettava "päivitystoiminto" end end luokka Palkkalaskenta < BaseObserver def update ( työntekijä ) p ( "Leikkaa uusi sekki henkilölle #{ työntekijä . nimi } !" ) p ( "Hänen palkkansa on nyt #{ työntekijä . palkka } !" ) end end luokka TaxMan < BaseObserver def update ( työntekijä ) p ( "Lähetä #{ työntekijä . nimi } uusi verolasku!" ) end end mike = Työntekijä . uusi ( 'Mike' , 'projektimies' , 25000 ) mike . add_observer ( Palkanlaskenta . uusi ) mike . Lisää_observer ( TaxMan . uusi ) mike . palkka = 35 000 mailia . title = 'vanhempi projektipäällikkö' mike . notify_observers =begin Tulos "Leikkaa uusi sekki Mikelle!" "Hänen palkkansa on nyt 35000!" "Lähetä Mikelle uusi verolasku!" = loppu

Ruoste

Lähdekoodi rustissa /// Esimerkki kuvaa kuinka vastaanottaa tietoja sääasemalta (WeatherData-rakenne, tapahtumanvälittäjä) ja /// käyttää sitä sen näyttämiseen näytöllä (CurrentConditionsDisplay-rakenne, tapahtuman kuuntelija). /// Kuuntelija rekisteröidään tarkkailijan kanssa register_observer-metodilla, joka sulkee ja /// lisää sen tarkkailijaluetteloon. Kun säätiedot muuttuvat, kutsutaan notify_observers-metodia, joka sulkee /// kaikki kuuntelijat ja välittää heille päivitetyt tiedot. käytä std :: rc :: Rc ; käytä std :: solua :: RefCell ; tyyppi ObserverFn = Laatikko < dyn Fn ( f32 , f32 , i32 ) > ; ominaisuus havaittavissa { fn register_observer ( & mut self , o : ObserverFn ) -> usize ; fn remove_observer ( & mut self , idx : use ); fn notify_observers ( & mut self ); } #[derive (oletus)] struct Säätiedot { tarkkailijat : Vec < ObserverFn > , lämpötila : f32 , kosteus : f32 , paine : i32 , } impl Säätiedot { fn set_measurements ( & mut self , lämpötila : f32 , kosteus : f32 , paine : i32 ) { itse . lämpötila = lämpötila ; itse . kosteus = kosteus ; itse . paine = paine ; itse . notify_observers (); } } impl Havaittavissa säätiedoille { _ fn register_observer ( & mut self , o : ObserverFn ) -> usize { itse . tarkkailijat . työnnä ( o ); itse . tarkkailijat . len () - 1 } fn remove_observer ( & mut self , idx : usize ) { itse . tarkkailijat . poista ( idx ); } fn notify_observers ( & mut self ) { itsenäinen tarkkailija . _ _ tarkkailijat . iter () { ( * tarkkailija )( itse . lämpötila , itse . kosteus , oma . paine ); } } } #[derive (oletus)] struct CurrentConditionsDisplay { lämpötila : f32 , kosteus : f32 , paine : i32 , } impl CurrentConditionsDisplay { fn näyttö ( & itse ) { println! ( "Nyt arvot ovat: {:.1} celsiusastetta ja {:.1} % kosteus. Paine {} mmHg." , itse . lämpötila , itse . kosteus , itse . paine ); } fn päivitys ( & mut self , lämpötila : f32 , kosteus : f32 , paine : i32 ) { itse . lämpötila = lämpötila ; itse . kosteus = kosteus ; itse . paine = paine ; itse . näyttö (); } } fn main () { let mut weather_data = Säätiedot :: oletus (); anna nykyisen_näyttö = Rc :: new ( RefCell :: new ( CurrentConditionsDisplay :: default ())); anna tarkkailija = nykyinen_näyttö . klooni (); weather_data . register_observer ( Laatikko :: uusi ( siirrä | t , h , p | tarkkailija . laina_mutti (). päivitä ( t , h , p ))); weather_data . set_measurements ( 29.0 , 65.0 , 745 ); weather_data . set_measurements ( 39.0 , 70.0 , 760 ); weather_data . set_measurements ( 42.0 , 72.0 , 763 ); }

io

Io lähdekoodi # Esimerkki on täysin identtinen yllä olevan Pythonin kanssa Observer : = Objektiklooni Observable := List clone do ( register := getSlot ( "push" ) notify := method ( viesti , self foreach ( tarkkailija , tarkkailijapäivitys ( viesti ))) ) Sanomalehti := Havaittava klooni do ( addNews : = metodi ( uutiset , ilmoittaa ( uutiset ))) Kansalainen := Tarkkailijan klooni do ( luo := metodi ( nimi , itse kloonattu lexicalDo ( nimi := nimi )) päivitys := menetelmä ( viesti , kirjoitusn ( nimi .. " selvitti: " .. viesti )) ) sanomalehti := Sanomalehden klooni sanomalehti do ( rekisteröidy ( Kansalainen luo ( "Ivan" ) )) rekisteröi ( Kansalainen luo ( "Vasily" ) ) addNews ( "Tarkkailija - käyttäytymismalli" ) #>>>> Ivan oppi seuraavaa: Observer on käyttäytymissuunnittelumalli #>>>> Vasily oppi seuraavaa: Observer on käyttäytymissuunnittelumalli

JavaScript ES6

Lähdeteksti javascriptissä class Havaittavissa { konstruktori () { tämä . kuuntelijat = {}; } // Tilaa. on ( e , takaisinsoitto ) { if ( tämä . kuuntelijat [ e ] == määrittelemätön ) { tämä . kuuntelijat [ e ] = {}; tämä . kuuntelijat [ e ]. eventProperty = {}; tämä . kuuntelijat [ e ]. tapahtumakiinteistö . isOnOnce = false ; tämä . kuuntelijat [ e ]. data = []; } tämä . kuuntelijat [ e ]. tiedot . push ( takaisinsoitto ); } // Tilaa kerran. onOnce ( e , takaisinsoitto ) { this . päällä ( e , takaisinsoitto ); tämä . kuuntelijat [ e ]. tapahtumakiinteistö . isOnOnce = tosi ; } // Lopeta tilaus. pois ( e , takaisinsoitto ) { this . kuuntelijat [ e ]. data = tämä . kuuntelijat [ e ]. tiedot . suodatin ( funktio ( kuuntelija ) { paluu kuuntelija !== takaisinsoitto ; }); } // Lähetä viesti tilaajille. emit ( e , data ) { if ( tämä . kuuntelijat [ e ] == undefined || this . kuuntelijat [ e ]. data == määrittelemätön ) { return ; } anna itObj = tämä ; tämä . kuuntelijat [ e ]. tiedot . forEach ( kuuntelija => { if ( itObj . kuuntelijat [ e ]. eventProperty . isOnOnce ) { itObj . off ( e , itObj . kuuntelijat [ e ]. data [ 0 ]); } kuuntelija ( data ); }); } }

Lisätietoja

.NET Framework 4.0 : ssa tarkkailijan suunnittelumalli on toteutettu toteuttamalla yleisiä rajapintoja System.IObservable<T>ja System.IObserver<T>[2] .

Kirjallisuus

  • Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides . Olio-suunnittelun tekniikat. Design Patterns = Design Patterns. Uudelleenkäytettävän olio-ohjelmiston osat. - Pietari. : Peter, 2009. - 366 s. - ISBN 978-5-469-01136-1 .
  • Eric Freeman, Elizabeth Freeman. Suunnittelukuviot = Head First Design Patterns. - Pietari. : Peter, 2011. - 656 s. - ISBN 978-5-459-00435-9 .

Muistiinpanot

  1. Tarkkailijakuvio . Haettu 13. kesäkuuta 2013. Arkistoitu alkuperäisestä 13. kesäkuuta 2013.
  2. 1 2 Tarkkailijan suunnittelukuvio . Haettu 13. kesäkuuta 2013. Arkistoitu alkuperäisestä 13. kesäkuuta 2013.
  3. Tarkkailijakuvio . Haettu 4. marraskuuta 2019. Arkistoitu alkuperäisestä 4. marraskuuta 2019.