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:
- Observerbar - ett gränssnitt som definierar metoder för att lägga till, ta bort och meddela observatörer;
- Observer - gränssnittet genom vilket observatören tar emot meddelandet;
- ConcreteObservable är en konkret klass som implementerar gränssnittet Observable;
- ConcreteObserver är en konkret klass som implementerar Observer-gränssnittet.
Omfattning
Observatörsmönstret används när systemet har följande egenskaper:
- det finns minst ett objekt som skickar meddelanden;
- det finns minst en mottagare av meddelanden, och deras antal och sammansättning kan ändras medan programmet körs;
- undviker stark koppling av interagerande klasser.
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
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 ();
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 );
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 . gå ();
// 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-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 );
}
}
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 & få () 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 . få () << 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 . få (). 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 ;
}
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 ;
}
}
}
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 . gå ()
" 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
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
'''
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 Gå ;
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 . gå ;
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 . gå () ; // Vänta på användarens readln ; äntligen observatör . Gratis ; observatör2 . Gratis ; ämne . Gratis ; slut ; slut .
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
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
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 . på ( 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
- ↑ Observatörsmönster . Hämtad 13 juni 2013. Arkiverad från originalet 13 juni 2013. (obestämd)
- ↑ 1 2 Observatörsdesignmönster . Hämtad 13 juni 2013. Arkiverad från originalet 13 juni 2013. (obestämd)
- ↑ Observatörsmönster . Hämtad 4 november 2019. Arkiverad från originalet 4 november 2019. (obestämd)