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:
- Observable - käyttöliittymä, joka määrittää menetelmät tarkkailijoiden lisäämiseksi, poistamiseksi ja ilmoittamiseksi;
- Tarkkailija - rajapinta, jonka kautta tarkkailija vastaanottaa ilmoituksen;
- ConcreteObservable on konkreettinen luokka, joka toteuttaa Observable-rajapinnan;
- ConcreteObserver on konkreettinen luokka, joka toteuttaa Observer-rajapinnan.
Laajuus
Tarkkailijakuviota käytetään, kun järjestelmällä on seuraavat ominaisuudet:
- on vähintään yksi objekti, joka lähettää viestejä;
- viesteillä on vähintään yksi vastaanottaja, ja niiden määrä ja koostumus voivat muuttua sovelluksen ollessa käynnissä;
- välttää vuorovaikutuksessa olevien luokkien vahvan kytkennän .
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 ();
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 );
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 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 );
}
}
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 ;
}
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 ;
}
}
}
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
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
'''
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 .
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
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
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
- ↑ Tarkkailijakuvio . Haettu 13. kesäkuuta 2013. Arkistoitu alkuperäisestä 13. kesäkuuta 2013. (määrätön)
- ↑ 1 2 Tarkkailijan suunnittelukuvio . Haettu 13. kesäkuuta 2013. Arkistoitu alkuperäisestä 13. kesäkuuta 2013. (määrätön)
- ↑ Tarkkailijakuvio . Haettu 4. marraskuuta 2019. Arkistoitu alkuperäisestä 4. marraskuuta 2019. (määrätön)