Observer (designmönster)

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 19 maj 2019; kontroller kräver 15 redigeringar .
Observatör
Observatör
Sorts beteendemässiga
Ändamål
  • Observer-mönstret definierar ett ett-till-många-beroende mellan objekt så att när tillståndet för ett objekt ändras, meddelas och uppdateras alla objekt som är beroende av det automatiskt;
  • Observatörsmönstret kapslar in den huvudsakliga (oberoende) komponenten i subjektabstraktionen och de föränderliga (beroende) komponenterna i observatörshierarkin;
  • Observatörsmönstret definierar "View"-delen av en Model-View-Controller (MVC) -modell [1] .
Beskrivs i Design Patterns Ja

The  Observer är ett beteendedesignmönster . _ _ Även känd som "underordnade" ( eng.  Dependents ). Implementerar en klassmekanism som tillåter ett objekt i denna klass att ta emot meddelanden om förändringar i tillståndet för andra objekt och därigenom observera dem [2] .

Klasser vars evenemang andra klasser prenumererar på kallas Subjects, och de prenumererande klasserna kallas Observers [ 3 ] . 

Liknande mallar: " publisher-subscriber ", " intermediary ", " loner ".

Utnämning

Definierar ett ett-till-många-beroende mellan objekt så att när tillståndet för ett objekt ändras får alla beroende av det ett meddelande om händelsen.

Implementering

När observatörsmönstret implementeras används vanligtvis följande klasser:

Omfattning

Observatörsmönstret används när systemet har följande egenskaper:

Detta mönster används ofta i situationer där avsändaren av meddelanden inte är intresserad av vad mottagarna gör med den information som de får.

Exempel

PHP5 (SPL)

Källtext på php-språk /** * PHP ger inbyggt stöd för detta mönster genom det medföljande * SPL (Standard PHP Library) tillägget: * SplObserver - gränssnitt för Observer (observatör), * SplSubject - gränssnitt för Observable (observerbar), * SplObjectStorage - hjälpklass (ger förbättrad lagring och radering av *-objekt, i synnerhet är metoderna attach() och detach() implementerade). */ class Observerbara redskap SplSubject { private $storage ; funktion __construct () { $this -> storage = new SplObjectStorage (); } function attach ( SplObserver $observer ) { $this -> storage -> attach ( $observer ); } function detach ( SplObserver $observer ) { $this -> storage -> detach ( $observer ); } function notify () { foreach ( $this -> lagring som $obj ) { $obj -> update ( $this ); } } } class ConcreteObserver implementerar SplObserver { private $observable ; privat $index ; function __construct ( Observerbar $observerbar ) { static $sindex = 0 ; $this -> index = $sindex ++ ; $this -> observable = $observable ; $observable -> bifoga ( $this ); } funktionsuppdatering ( SplSubject $subject ) { if ( $ subject === $this -> observable ) { echo "Skicka meddelande till ConcreteObserver [ $this->index ] \n " ; } } } $observable = new Observable (); ny ConcreteObserver ( $observable ); ny ConcreteObserver ( $observable ); ny ConcreteObserver ( $observable ); $observable -> meddela ();

PHP5

Källtext på php-språk gränssnitt Observer { function notify ( $obj ); } class ExchangeRate { static private $instance = NULL ; privata $observatörer = array (); privat $exchange_rate ; privat funktion __construct () {} privat funktion __clone () {} statisk offentlig funktion getInstance () { if ( self :: $instance == NULL ) { self :: $instance = new ExchangeRate (); } returnera själv :: $instans ; } public function getExchangeRate () { return $this -> exchange_rate ; } offentlig funktion setExchangeRate ( $new_rate ) { $this -> exchange_rate = $new_rate ; $this -> notifyObservers (); } public function registerObserver ( Observer $obj ) { $this -> observers [] = $obj ; } function notifyObservers () { foreach ( $this -> observers as $obj ) { $obj -> notify ( $this ); } } } class ProductItem implementerar Observer { public funktion __construct () { ExchangeRate :: getInstance () -> registerObserver ( $this ); } public function notify ( $obj ) { if ( $obj instanceof ExchangeRate ) { // Uppdatera växelkursdata print "Mottog uppdatering! \n " ; } } } $product1 = new ProductItem (); $product2 = new ProductItem (); ExchangeRate :: getInstance () -> setExchangeRate ( 4.5 );

C#

Källtext i C# använder System ; använder System.Collections ; använder System.Collections.Generic ; använder System.Threading ; namnområde Observer { /// <sammanfattning> /// Observatörsmönster Judith Bishop Jan 2007 /// Uppdaterad av Kobel' Bohdan 2013 /// /// Ämnet körs i en tråd och ändrar dess tillstånd /// oberoende. Vid varje ändring meddelar den sina observatörer. /// </summary> class Program { static void Main ( string [] args ) { Subject subject = new Subject (); Observer observer = new Observer ( subject , "Center" , "\t\t" ); Observer observer2 = new Observer ( ämne , "Höger" , "\t\t\t\t" ); ämne . (); // Vänta på användarkonsolen . läs (); } } class Simulator : IEnumerable { string [] moves = { "5" , "3" , "1" , "6" , "7" }; public IEnumerator GetEnumerator ( ) { foreach ( strängelement i drag ) yield return element ; } } gränssnitt ISubject { void AddObserver ( IObserver observer ); void RemoveObserver ( IObserver observer ); void NotifyObservers ( sträng s ); } class Subject : ISubject { public string SubjectState { get ; set ; } public List < IObserver > Observers { get ; privat set ; } privat simulatorsimulator ; _ privat konstant int hastighet = 200 ; public Subject () { Observers = new List < IObserver >(); simulator = ny Simulator (); } public void AddObserver ( IObserver observer ) { Observers . Lägg till ( observatör ); } public void RemoveObserver ( IObserver observer ) { Observers . Ta bort ( observatör ); } public void NotifyObservers ( sträng s ) { foreach ( var observer i Observers ) { observer . Uppdatering ( er ); } } public void Go () { new Thread ( new ThreadStart ( Run )). Start ( ); } void Run () { foreach ( sträng är i simulator ) { Console . WriteLine ( "Ämne: " + s ); SubjectState = s ; NotifyObservers ( er ); tråd . sömn ( hastighet ); // millisekunder } } } gränssnitt IObserver { void Update ( strängtillstånd ) ; } class Observer : IObserver { strängnamn ; _ Ämnesämne ; _ strängtillstånd ; _ stränggap ; _ public Observer ( ISubject subject , string name , string gap ) { this . ämne = ämne ; detta . namn = namn ; detta . gap = gap ; ämne . AddObserver ( detta ); } public void Uppdatering ( sträng subjectState ) { state = subjectState ; Konsol . WriteLine ( gap + namn + ": " + tillstånd ); } } }

Java

Java-källa // Exemplet beskriver hur man tar emot data från en väderstation (WeatherData-klass, händelseförmedlare) och //använder den för att visa den på skärmen (CurrentConditionsDisplay-klass, händelseavlyssnare). //Avlyssnaren registreras hos observatören med hjälp av registerObserver-metoden (i detta fall läggs lyssnaren till i listan över observatörer). //Registrering sker i det ögonblick det aktuella Display-objektet skapas, eftersom metoden registerObserver tillämpas i konstruktorn. //När väderdata ändras anropas notifyObservers-metoden, som i sin tur anropar uppdateringsmetoden //på alla lyssnare och skickar den uppdaterade datan till dem. importera java.util.LinkedList ; importera java.util.List ; public class WeatherStation { public static void main ( String [] args ) { WeatherData weatherData = new WeatherData (); Observer currentDisplay = new CurrentConditionsDisplay (); väderdata . registerObserver ( aktuell Display ); väderdata . setMeasurements ( 29 f , 65 f , 745 ); väderdata . setMeasurements ( 39 f , 70 f , 760 ); väderdata . setMeasurements ( 42 f , 72 f , 763 ); } } gränssnitt Observer { void update ( float temperatur , float fuktighet , int tryck ) ; } gränssnitt Observable { void registerObserver ( Observer o ); void removeObserver ( Observer o ); void notifyObservers (); } class WeatherData implementerar observerbar { privat lista < Observer > observatörer ; privat flyttemperatur ; _ privat flytfuktighet ; _ privat int tryck ; public WeatherData () { observers = new LinkedList <> (); } @Override public void registerObserver ( Observer o ) { observers . lägg till ( o ); } @Override public void removeObserver ( Observer o ) { observers . ta bort ( o ); } @Override public void notifyObservers () { for ( Observer observer : observers ) observer . uppdatering ( temperatur , luftfuktighet , tryck ); } public void setMeasurements ( flottemperatur , flytfuktighet , int tryck ) { detta . _ _ temperatur = temperatur ; detta . fuktighet = fuktighet ; detta . tryck = tryck ; notifyObservers (); } } class CurrentConditionsDisplay implementerar Observer { privat flyttemperatur ; _ privat flytfuktighet ; _ privat int tryck ; @ Åsidosätt offentlig void - uppdatering ( flyttemperatur , flytfuktighet , int tryck ) { detta . temperatur = temperatur ; detta . fuktighet = fuktighet ; detta . tryck = tryck ; visa (); } public void display () { System . ut . printf ( "Nu är värdena: %.1f grader Celsius och %.1f %% fuktighet. Tryck %d mmHg\n" , temperatur , fuktighet , tryck ); } }

C++

Källtext i C++ #include <iostream> #inkludera <sträng> #inkludera <lista> använder namnutrymme std ; klass SupervisedString ; klass IObserver { offentliga : virtual void handleEvent ( const SupervisedString & ) = 0 ; }; class SupervisedString // Observerbar klass { string_str ; _ lista < IObserver *> _observatörer ; void _Meddela () { för ( auto & observer : _observatörer ) { observer -> handleEvent ( * detta ); } } offentliga : void add ( IObserver & ref ) { _observatörer . push_back ( & ref ); } void remove ( IObserver & ref ) { _observatörer . ta bort ( & ref ); } const sträng & () const { return_str ; _ } void reset ( string str ) { _str = str ; _Meddela (); } }; class Reflector : public IObserver // Skriver ut den observerade strängen i cout { offentliga : virtual void handleEvent ( const SupervisedString & ref ) { cout << ref . () << endl ; } }; class Counter : public IObserver // Skriver ut längden på observerad sträng till cout { offentliga : virtual void handleEvent ( const SupervisedString & ref ) { cout << "längd = " << ref . (). längd () << endl ; } }; int main () { SupervisedString str ; reflektor refl ; Counter cnt ; str . add ( refl ); str . återställ ( "Hej världen!" ); cout << endl ; str . ta bort ( refl ); str . add ( cnt ); str . återställ ( "Världen, hej!" ); cout << endl ; returnera 0 ; }

ActionScript

Källtext i ActionScript //file IObserver.as paket { public interface IObserver { function notify ( obj : Object ): void ; } } //file ExchangeRate.as paket { public class ExchangeRate { private static var _instance : ExchangeRate = null ; private var observers : Array = []; privat var _exchangeRate : Objekt ; public function ExchangeRate () { if ( _instance == null ) throw new Error ( 'Model Singleton!' ); } offentlig statisk funktion getInstance (): ExchangeRate { if ( _instance == null ) _instance = new ExchangeRate (); returnera _instans ; } public function get exchangeRate (): Objekt { return _exchangeRate ; } offentlig funktionsuppsättning exchangeRate ( värde : Objekt ) : void { _exchangeRate = värde ; detta . notifyObservers (); } public function registerObserver ( värde : IObserver ): void { this . observatörer . push ( värde ); } privat funktion notifyObservers (): void { för varje ( var observer : IObserver i denna . observers ) { observer . meddela ( detta ); } } } } //file ProductItem.as- paketet { public class ProductItem implementerar IObserver { public function ProductItem () { ExchangeRate . getInstance (). registerObserver ( detta ); } public function notify ( värde : Objekt ): void { if ( värdet är ExchangeRate ) { var exchange : ExchangeRate = värde som ExchangeRate ; spåra ( exchange.exchangeRate ) ; _ } } } } //file Main.as- paket { import flash.display.Sprite ; public class Main utökar Sprite { public function Main (): void { var item1 : ProductItem = new ProductItem (); var item2 : ProductItem = new ProductItem (); ExchangeRate . getInstance (). växelkurs = 3,5 ; } } }

VB.NET

Källtext på språket VB.NET Importer System.Collections Importer System.Threading Namnområde Observatör ''' <sammanfattning> ''' Observatörsmönster Judith Bishop Jan 2007 ''' ''' Ämnet körs i en tråd och ändrar sitt tillstånd ''' oberoende. Vid varje ändring meddelar den sina observatörer. ''' </summary> Klass Program Delat Under Huvud () Dim ämne Som nytt ämne () Dim observatör Som ny observatör ( ämne , "Center" , vbTab & vbTab ) Dim observer2 Som ny observatör ( ämne , "Höger" , vbTab & vbTab & vbTab & vbTab ) ämne . () " Vänta på användarkonsolen . Läs () End Sub slutklass _ Klasssimulatorn implementerar IEnumerable Private moves As String ( ) = { "5" , "3" , "1" , "6" , "7" } Offentlig funktion GetEnumerator () Som IEnumerator implementerar IEnumerable . GetEnumerator Return flyttar . GetEnumerator ' // Yield End Function End Class Klass Subject Public Delegate Sub Callback ( ByVal s As String ) Public Event Notify As Callback Privat simulator Som Ny Simulator () Privat m_SubjectState Som String Privat Konst hastighet Som heltal = 200 Public Property SubjectState () As String Get Return m_SubjectState End Get Set ( ByVal value As String ) m_SubjectState = value End Set End Property Public Sub Go () Call ( New Thread ( New ThreadStart ( AddressOf Run ))). Start () Slut Sub Privat underkörning ( ) för varje s som sträng i simulatorkonsol . _ WriteLine ( "Subject: " & s ) SubjectState = s RaiseEvent Notify ( s ) ' milliseconds Thread . Sömn ( hastighet ) Next End Sub End Class Gränssnitt IObserver Sub Update ( ByVal state As String ) Slutgränssnitt _ Class Observer implementerar IObserver Privat namn Som sträng Privat ämne Som Ämne Privat tillstånd Som sträng Privat lucka Som sträng Public Sub New ( ByVal subject As Subject , ByVal name As String , ByVal gap As String ) Me . ämne = ämne Jag . namn = namnge mig . gap = gap AddHandler ämne . Meddela , AddressOf Update End Sub Public Sub Update ( ByVal subjectState As String ) Implementerar IObserver . Uppdatera tillstånd = subjectStateConsole . _ WriteLine ( gap & name & ": " & state ) End Sub End Class End Namespace

Python

Källkod i Python från abc import ABCMeta , abstraktmetod class Observer ( metaclass = ABCMeta ): """ Abstrakt observatör """ @abstractmethod def update ( self , message : str ) -> None : """ Få nytt meddelande """ pass klass Observerbar ( metaklass = ABCMeta ): """ Abstrakt observerbar """ def __init__ ( self ) -> None : """ Konstruktör. """ self . observatörer = [] # initiering av listan över observatörer def register ( self , observer : Observer ) -> None : """ Registrera en ny observatör för att prenumerera på """ själv . observatörer . lägga till ( observatör ) def notify_observers ( self , message : str ) -> None : """ Skicka ett meddelande till alla observatörer som prenumererar på händelserna för det givna objektet i den observerbara klassen """ för observer in self . observatörer : observatör . uppdatera ( meddelande ) klass Tidning ( observerbar ): """ En tidning som följs av tusentals människor """ def add_news ( self , news : str ) -> None : """ Nytt pressmeddelande """ self . notify_observers ( nyheter ) klass Citizen ( Observer ): """ En vanlig medborgare som gillar att läsa sin favorittidning på morgonen """ def __init__ ( själv , namn : str ) -> Ingen : """ Konstruktör. :param name: namnet på medborgaren, för att inte förväxla honom med någon annan """ self .name = name def update ( self , message : str ) -> None : """ Få nästa nyhet """ print ( f ' { self . name } lärde sig följande: { message } ' ) if __name__ == '__main__' : tidning = Tidning () # skapa en liten tidningstidning . registrera ( Medborgare ( 'Ivan' )) # lägg till två personer som är tidningar . registrera ( Medborgare ( 'Vasily' )) # ... det är regelbundet prenumererat # ... och vi slänger in en annan tidning duck tidning . add_news ( 'Observer - Behavioral Design Pattern' ) ''' Ivan lärde sig följande: Observer - Behavioral Design Pattern Vasily lärde sig följande: Observer - Behavioral Design Pattern '''

ObjectPascal

Källtext i Object Pascal (Delphi) programobservatör ; _ /// Observatörsmönster Judith Bishop Jan 2007 /// Portad till Pascal av Dmitry Boyarintsev, maj 2018 /// /// Ämnet körs i en tråd och ändrar tillstånd /// oberoende. Vid varje ändring meddelar den sina observatörer. {$ifdef fpc}{$mode delphi}{$H+}{$endif} använder SysUtils , Classes ; typ TBaseObserver = klass ( TObject ) procedur Uppdatering ( const astate : string ) ; virtuell ; abstrakt ; slut ; TBaseSubject = klass ( TObject ) procedur AddObserver ( aobserver : TBaseObserver ) ; virtuell ; abstrakt ; procedur RemoveObserver ( aobserver : TBaseObserver ) ; virtuell ; abstrakt ; procedure NotifyObservers ( const s : string ) ; virtuell ; abstrakt ; slut ; typ { TÄmne } TSubject = klass ( TBaseSubject ) privata fObservers : TList ; fSimulator : TStringList ; hastighet : heltal ; skyddad procedur Kör ; offentlig konstruktör Skapa ; förstörare Destroy ; åsidosätta ; procedur AddObserver ( aobserver : TBaseObserver ) ; åsidosätta ; procedur RemoveObserver ( aobserver : TBaseObserver ) ; åsidosätta ; procedure NotifyObservers ( const astate : string ) ; åsidosätta ; procedur ; slut ; TObserver = klass ( TBaseObserver ) privat fname : string ; fsubject : TBaseSubject ; fstate : sträng _ fgap : sträng _ offentlig konstruktör Skapa ( asubject : TBaseSubject ; const aname , agap : sträng ) ; procedur Update ( const astate : string ) ; åsidosätta ; slut ; { TÄmne } procedur TÄmne . springa ; var i : heltal ; s : sträng _ börja för i := 0 till fSimulator . Räkna - 1 börjar s : = fSimulator [ i ] ; Writeln ( 'Ämne: ' , s ) ; NotifyObservers ( er ) ; Sömn ( hastighet ) ; // millisekunder slut ; slut ; konstruktör TSubject . skapa ; börja ärvt Skapa ; fObservers := TList . skapa ; hastighet := 200 ; fSimulator := TStringList . skapa ; fSimulator . AddStrings ([ '5' , '3' , '1' , '6' , '7' ]) ; slut ; förstörare TÄmne . Förstöra ; börja fObservatörer . Gratis ; fSimulator . Gratis ; slut ; procedur TÄmne . AddObserver ( aobserver : TBaseObserver ) ; börja fObservatörer . Lägg till ( aobserver ) ; slut ; procedur TÄmne . RemoveObserver ( aobserver : TBaseObserver ) ; börja fObservatörer . Ta bort ( aobserver ) ; slut ; procedur TÄmne . NotifyObservers ( const astate : sträng ) ; var i : heltal ; börja för i := 0 till fObservers . Räkna - 1 till TBaseObserver ( fObservers [ i ]) . Uppdatering ( astate ) ; slut ; typ { TmethodThread } TMethodThread = klass ( TTread ) skyddad fMethod : TThreadMethod ; procedur Utför ; åsidosätta ; public constructor Create ( AMethod : TThreadMethod ) ; slut ; { TmethodThread } konstruktör TmethodThread . Skapa ( Amethod : TThreadMethod ) ; börja fMethod := Amethod ; FreeOnTerminate := Sant ; ärvt Skapa ( falskt ) ; slut ; procedur TmethodThread . Utför ; börja om Tilldelad ( fMethod ) sedan fMethod () ; slut ; procedur TÄmne . ; börja TmethodThread . Skapa ( Self.Run ) ; _ _ slut ; konstruktör TObserver . Skapa ( asubject : TBaseSubject ; const aname , agap : string ) ; börja ärvt Skapa ; fsubject := assubject ; fname := aname ; fgap := agap ; om Tilldelad ( fsubject ) sedan fsubject . AddObserver ( själv ) ; slut ; procedur TObserver . Uppdatera ( const astate : sträng ) ; börja fstate := astate ; writeln ( fgap , fname , ':' , astate ) ; slut ; /// Huvudprogram var subject : TSubject ; observatör : TObserver ; observer2 : TObserver ; beginsubject : = TÄmne . skapa ; observer := TObserver . Skapa ( ämne , 'Center' , #9#9 ) ; observer2 := TObserver . Skapa ( ämne , 'Höger' , #9#9#9#9 ) ; prova ämnet . () ; // Vänta på användarens readln ; äntligen observatör . Gratis ; observatör2 . Gratis ; ämne . Gratis ; slut ; slut .

Ruby

Ruby källkod modul Observerbar def initiera @observatörer = [] slut def add_observer ( observatör ) @ observatörer << observatör om inte @ observatörer . omfatta? ( observatör ) slut def delete_observer ( observatör ) @ observatörer . radera ( observatör ) sluta def notify_observers @observatörer . varje { | x | x . uppdatera ( själv )} slut slut klass Anställd inkluderar observerbar attr_reader :namn attr_accessor :titel , :lön def initiera ( namn , titel , lön ) super () @namn = namn @titel = titel @ lön = slutlön slut klass BaseObserver def update höja 'Måste implementera "uppdaterings" funktion' slutet slut klass Lön < BaseObserver def update ( anställd ) p ( " Klipp en ny check för #{ anställd . namn } !" ) p ( " Hans lön är nu # { anställd . lön } !" ) slut slut class TaxMan < BaseObserver def update ( anställd ) p ( "Skicka #{ anställd . namn } en ny skattesedel!" ) end end mike = Anställd . ny ( 'Mike' , 'projektledare' , 25000 ) mike . add_observer ( Lön . ny ) mike . add_observer ( TaxMan . ny ) mike . lön = 35000 mike . title = 'senior projektledare' mike . notify_observatörer =begin Resultatet av "Klipp en ny check för Mike!" "Hans lön är nu 35 000!" "Skicka en ny skattesedel till Mike!" =slut

Rost

Källkod i Rust /// Exemplet beskriver hur man tar emot data från en väderstation (WeatherData-struktur, händelseförmedlare) och /// använder den för att visa den på skärmen (CurrentConditionsDisplay-struktur, händelseavlyssnare). /// Lyssnaren registreras hos observatören med metoden register_observer, som tar en stängning och /// lägger till den i listan över observatörer. När väderdatan ändras anropas notify_observers-metoden, som stänger /// alla lyssnare och skickar den uppdaterade datan till dem. använd std :: rc :: Rc ; använd std :: cell :: RefCell ; typ ObserverFn = Box < dyn Fn ( f32 , f32 , i32 ) > ; egenskap observerbar { fn register_observer ( & mut self , o : ObserverFn ) -> usize ; fn remove_observer ( & mut self , idx : usize ); fn notify_observers ( & mut self ); } #[derive(Standard)] struct WeatherData { observatörer : Vec < ObserverFn > , temperatur : f32 , luftfuktighet : f32 , tryck : i32 , } impl WeatherData { fn set_measurements ( & mut self , temperatur : f32 , fuktighet : f32 , tryck : i32 ) { själv . temperatur = temperatur ; själv . fuktighet = fuktighet ; själv . tryck = tryck ; själv . notify_observers (); } } impl observerbar för WeatherData { fn register_observer ( & mut self , o : ObserverFn ) -> usize { själv . observatörer . trycka ( o ); själv . observatörer . len () - 1 } fn remove_observer ( & mut self , idx : usize ) { själv . observatörer . ta bort ( idx ); } fn notify_observers ( & mut self ) { för iakttagare i sig själv . observatörer . iter () { ( * observatör )( själv . temperatur , själv . fuktighet , själv . tryck ); } } } #[derive(Standard)] struct CurrentConditionsDisplay { temperatur : f32 , luftfuktighet : f32 , tryck : i32 , } impl CurrentConditionsDisplay { fn display ( & self ) { println! ( "Nu är värdena: {:.1} grader Celsius och {:.1} % luftfuktighet. Tryck {} mmHg." , själv . temperatur , själv . fuktighet , själv . tryck ); } fn update ( & mut self , temperatur : f32 , fuktighet : f32 , tryck : i32 ) { själv . temperatur = temperatur ; själv . fuktighet = fuktighet ; själv . tryck = tryck ; själv . visa (); } } fn main () { let mut weather_data = WeatherData :: default (); let current_display = Rc :: new ( RefCell :: new ( CurrentConditionsDisplay :: default ())); låt observer = aktuell_visning . klon (); väder_data . register_observer ( Box :: new ( flytta | t , h , p | observer . borrow_mut (). uppdatera ( t , h , p ))); väder_data . set_measurements ( 29.0 , 65.0 , 745 ); väder_data . set_measurements ( 39.0 , 70.0 , 760 ); väder_data . set_measurements ( 42.0 , 72.0 , 763 ); }

io

Io källkod # Ett exempel är helt identiskt med det ovan i Python Observer : = Objektklon Observerbar := Lista klon gör ( registrera := getSlot ( "push" ) meddela := metod ( meddelande , self foreach ( observatör , observatörsuppdatering ( meddelande ))) ) Tidning := Observerbar klon gör ( addNews : = metod ( nyheter , meddela ( nyheter ))) Citizen := Observer clone do ( skapa := metod ( namn , självklona lexicalDo ( namn := namn )) uppdatera := metod ( meddelande , skrivln ( namn .. " fick reda på: " .. meddelande ) ) ) tidning : = Tidningsklon tidning gör ( registrera ( Medborgarskapa ( "Ivan" ) )) registrera ( Medborgarskapa ( "Vasily" ) ) addNews ( " Observer - Behavioral Design Pattern" ) ) #>>>> Ivan lärde sig följande: The Observer är ett beteendedesignmönster #>>>> Vasily lärde sig följande: The Observer är ett beteendedesignmönster

JavaScript ES6

Källtext i javascript klass Observerbar { konstruktor () { detta . lyssnare = {}; } // Prenumerera. on ( e , callback ) { if ( this . listeners [ e ] == undefined ) { this . lyssnare [ e ] = {}; detta . lyssnare [ e ]. eventProperty = {}; detta . lyssnare [ e ]. eventProperty . isOnce = false ; detta . lyssnare [ e ]. data = []; } detta . lyssnare [ e ]. data . push ( återuppringning ); } // Prenumerera en gång. onOnce ( e , callback ) { this . ( e , återuppringning ); detta . lyssnare [ e ]. eventProperty . ärOnOnce = sant ; } // Säga upp. off ( e , callback ) { detta . lyssnare [ e ]. data = detta . lyssnare [ e ]. data . filter ( funktion ( lyssnare ) { return listener !== callback ; }); } // Skicka meddelande till prenumeranter. emit ( e , data ) { if ( this . listeners [ e ] == odefinierad || this . listeners [ e ]. data == odefinierad ) { return ; } låt itObj = detta ; detta . lyssnare [ e ]. data . forEach ( lyssnare => { if ( itObj . lyssnare [ e ]. eventProperty . isOnce ) { itObj . off ( e , itObj . lyssnare [ e ]. data [ 0 ]); } lyssnare ( data ); }); } }

Ytterligare information

I .NET Framework 4.0 implementeras observatörsdesignmönstret genom att implementera generiska gränssnitt System.IObservable<T>och System.IObserver<T>[2] .

Litteratur

  • Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides . Tekniker för objektorienterad design. Designmönster = Designmönster. Element av återanvändbar objektorienterad programvara. - St Petersburg. : Peter, 2009. - 366 sid. - ISBN 978-5-469-01136-1 .
  • Eric Freeman, Elizabeth Freeman. Designmönster = Head First Design Patterns. - St Petersburg. : Peter, 2011. - 656 sid. - ISBN 978-5-459-00435-9 .

Anteckningar

  1. Observatörsmönster . Hämtad 13 juni 2013. Arkiverad från originalet 13 juni 2013.
  2. 1 2 Observatörsdesignmönster . Hämtad 13 juni 2013. Arkiverad från originalet 13 juni 2013.
  3. Observatörsmönster . Hämtad 4 november 2019. Arkiverad från originalet 4 november 2019.