Megfigyelő (tervezési minta)
Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2019. május 19-én felülvizsgált
verziótól ; az ellenőrzések 15 szerkesztést igényelnek .
Megfigyelő |
---|
Megfigyelő |
|
Típusú |
viselkedési |
Célja |
- Az Observer minta egy-többhöz függőséget határoz meg az objektumok között, így ha egy objektum állapota megváltozik, az összes attól függő objektum automatikusan értesítést kap és frissül;
- Az Observer minta a fő (független) komponenst tartalmazza a Tárgy absztrakcióban és a változtatható (függő) komponenseket a Megfigyelő hierarchiában;
- Az Observer minta egy Model-View-Controller (MVC) modell "View" részét határozza meg [1] .
|
Leírása: Tervezési minták |
Igen |
Az Observer egy viselkedési tervezési minta . _ Más néven "beosztottak" ( eng. Dependents ). Osztálymechanizmust valósít meg, amely lehetővé teszi, hogy ennek az osztálynak az objektumai értesítéseket kapjanak más objektumok állapotának változásairól, és ezáltal megfigyeljék azokat [2] .
Azokat az osztályokat, amelyek eseményeire más osztályok előfizetnek, alanyoknak, a feliratkozó osztályokat Observereknek
[ 3 ] nevezzük .
Hasonló sablonok: " kiadó-előfizető ", " közvetítő ", " magányos ".
Időpont
Egy a többhez függőséget határoz meg az objektumok között, így amikor egy objektum állapota megváltozik, az összes tőle függő értesítést kap az eseményről.
Megvalósítás
A megfigyelői minta implementálásakor általában a következő osztályokat használják:
- Megfigyelhető - olyan interfész, amely meghatározza a megfigyelők hozzáadásának, eltávolításának és értesítésének módszereit;
- Megfigyelő - az a felület, amelyen keresztül a megfigyelő megkapja az értesítést;
- A ConcreteObservable egy konkrét osztály, amely megvalósítja az Observable interfészt;
- A ConcreteObserver egy konkrét osztály, amely megvalósítja az Observer felületet.
Hatókör
A megfigyelő mintát akkor használjuk, ha a rendszer a következő tulajdonságokkal rendelkezik:
- van legalább egy objektum, amely üzeneteket küld;
- az üzeneteknek legalább egy címzettje van, és számuk és összetételük változhat az alkalmazás futása közben;
- elkerüli az egymásra ható osztályok erős összekapcsolását .
Ezt a mintát gyakran alkalmazzák olyan helyzetekben, amikor az üzenet küldőjét nem érdekli, mit kezdenek a címzettek a nekik adott információval.
Példák
Forrás szöveg php nyelven
/**
* A PHP beépített támogatást biztosít ehhez a mintához a mellékelt
* SPL (Standard PHP Library) kiterjesztésen keresztül:
* SplObserver - interfész az Observer számára (megfigyelő),
* SplSubject - a megfigyelhető (megfigyelhető),
* SplObjectStorage - segédosztály (javított
* objektumok mentését és törlését biztosítja, különös tekintettel az attach() és detach() metódusok megvalósítására).
*/
class Megfigyelhető implements SplSubject
{
private $storage ;
function __construct ()
{
$this -> storage = new SplObjectStorage ();
}
function csatolás ( SplObserver $observer )
{
$this -> storage -> attach ( $observer );
}
function detach ( SplObserver $observer )
{
$this -> storage -> detach ( $observer );
}
function notify ()
{
foreach ( $this -> storage as $obj )
{
$obj -> update ( $this );
}
}
}
class ConcreteObserver implementálja a SplObservert
{
private $megfigyelhető ;
privát $index ;
function __construct ( Megfigyelhető $megfigyelhető )
{
static $sindex = 0 ;
$this -> index = $sindex ++ ;
$ez -> megfigyelhető = $megfigyelhető ;
$megfigyelhető -> csatolja ( $this );
}
function update ( SplSubject $subject )
{
if ( $subject === $this -> observable )
{
echo "Értesítés küldése a ConcreteObservernek [ $this->index ] \n " ;
}
}
}
$megfigyelhető = new Megfigyelhető ();
új ConcreteObserver ( $megfigyelhető );
új ConcreteObserver ( $megfigyelhető );
új ConcreteObserver ( $megfigyelhető );
$megfigyelhető -> értesít ();
Forrás szöveg php nyelven
interface Observer
{
function notify ( $obj );
}
class Árfolyam
{
static private $példány = NULL ;
privát $megfigyelők = array ();
privát $árfolyam ;
privát függvény __construct ()
{}
privát függvény __klón ()
{}
static public function getInstance ()
{
if ( self :: $példány == NULL )
{
self :: $példány = new ExchangeRate ();
}
return self :: $példány ;
}
public function getExchangeRate ()
{
return $this -> árfolyam ;
}
public function setExchangeRate ( $új_árfolyam )
{
$this -> árfolyam = $új_árfolyam ;
$this -> notifyObservers ();
}
public function registerObserver ( Observer $obj )
{
$this -> megfigyelők [] = $obj ;
}
function notifyObservers ()
{
foreach ( $this -> megfigyelők mint $obj )
{
$obj -> notify ( $this );
}
}
}
osztály ProductItem megvalósítja az Observert
{
public function __construct ()
{
ExchangeRate :: getInstance () -> registerObserver ( $this );
}
public function notify ( $obj )
{
if ( $obj instanceof ExchangeRate )
{
// Árfolyamadatok frissítése
print "Frissítés érkezett! \n " ;
}
}
}
$termék1 = új termékelem ();
$termék2 = új Termékelem ();
ExchangeRate :: getInstance () -> setExchangeRate ( 4.5 );
Forrásszöveg C# nyelven
a rendszer használatával ;
a System.Collections használatával ;
a System.Collections.Generic használatával ;
a System.Threading használatával ;
névtér Megfigyelő
{
/// <összefoglaló>
/// Observer Pattern Judith Bishop 2007. jan.
/// Frissítette: Kobel' Bohdan 2013
/// /// Az alany egy szálban fut, és
/// függetlenül változtatja állapotát .
Minden változásnál értesíti a Megfigyelőit.
/// </summary>
class Program
{
static void Main ( string [] args )
{
Subject tárgy = new Subject ();
Megfigyelő megfigyelő = new Observer ( tárgy , "Közép" , "\t\t" );
Observer megfigyelő2 = new Observer ( tárgy , "Jobb" , "\t\t\t\t" );
tárgy . megy ();
// Várja meg a felhasználói
konzolt . olvasni ();
}
}
class Simulator : IEnumerable
{
string [] moves = { "5" , "3" , "1" , "6" , "7" };
public IEnumerator GetEnumerator ()
{
foreach ( karakterlánc elem a mozgásokban )
hozam return elem ;
}
}
interface ISubject
{
void AddObserver ( IObserver megfigyelő );
void RemoveObserver ( IObserver megfigyelő );
void NotifyObservers ( string s );
}
class Tárgy : ISubject
{
public string SubjectState { get ; készlet ; }
public List < IObserver > Megfigyelők { get ; magánkészlet ; _ }
privát szimulátor szimulátor ;
privát const int sebesség = 200 ;
public Subject ()
{
Megfigyelők = new List < IObserver >();
szimulátor = új Szimulátor ();
}
public void AddObserver ( IObserver megfigyelő )
{
Megfigyelők . Add ( megfigyelő );
}
public void RemoveObserver ( IObserver megfigyelő )
{
Megfigyelők . Eltávolítás ( megfigyelő );
}
public void NotifyObservers ( karakterláncok ) { foreach ( var megfigyelő a Megfigyelőkben ) { megfigyelő . _ Frissítés ( ek ); } }
public void Go ()
{
new Thread ( new ThreadStart ( Futtatás )). Indítás ( );
}
void Futtatás ( )
{
foreach ( karakterlánc a szimulátorban ) { Konzol . WriteLine ( "Tárgy: " + s ); SubjectState = s ; NotifyObservers ( ek ); szál . alvás ( sebesség ); // ezredmásodperc } } }
interface IObserver
{
void Frissítés ( karakterlánc állapota );
}
class Megfigyelő : IObserver
{
string name ;
IStárgy tárgy ;
karakterlánc állapota ;
húrrés ; _
public Observer ( ISubject tárgy , karakterlánc neve , string gap )
{
this . tárgy = alany ;
ezt . név = név ;
ezt . rés = rés ;
tárgy . AddObserver ( ez );
}
public void Frissítés ( string subjectState )
{
state = tárgyállapot ;
Konzol . WriteLine ( hézag + név + ": " + állapot );
}
}
}
Java forrás
// A példa leírja, hogyan lehet adatokat fogadni egy meteorológiai állomástól (WeatherData osztály, esemény diszpécser) és
//azokat használni a képernyőn való megjelenítéséhez (CurrentConditionsDisplay osztály, eseményfigyelő).
//A figyelő a registerObserver metódussal van regisztrálva a megfigyelőnél (ebben az esetben a figyelő felkerül a megfigyelők listájára).
//A regisztráció a currentDisplay objektum létrehozásának pillanatában történik, mert a registerObserver metódust alkalmazzuk a konstruktorban.
//Amikor az időjárási adatok megváltoznak, a notifyObservers metódus meghívásra kerül, ami viszont meghívja az update metódust
//az összes hallgatón, átadva nekik a frissített adatokat.
import java.util.LinkedList ;
import java.util.List ;
public class WeatherStation {
public static void main ( String [] args ) {
WeatherData weatherData = new WeatherData ();
Observer currentDisplay = new CurrentConditionsDisplay ();
időjárásadatok . registerObserver ( currentDisplay );
időjárásadatok . setMeasurements ( 29 f , 65 f , 745 );
időjárásadatok . setMeasurements ( 39 f , 70 f , 760 );
időjárásadatok . setMeasurements ( 42 f , 72 f , 763 );
}
}
interfész Observer {
void update ( lebegő hőmérséklet , úszó páratartalom , belső nyomás );
}
interface Megfigyelhető {
void registerObserver ( Observer o );
void removeObserver ( Observer o );
void notifyObservers ();
}
osztály WeatherData megvalósítja a Megfigyelhető {
private List < Observer > megfigyelőket ;
privát úszó hőmérséklet ;
privát úszó páratartalom ;
privát int nyomás ;
public WeatherData () {
megfigyelők = new LinkedList <> ();
}
@Override
public void registerObserver ( Observer o ) {
megfigyelők . add ( o );
}
@Override
public void removeObserver ( Observer o ) {
megfigyelők . eltávolítás ( o );
}
@Override
public void notifyObservers () {
for ( Megfigyelő megfigyelő : megfigyelők )
megfigyelő . frissítés ( hőmérséklet , páratartalom , nyomás );
}
public void setMeasurements ( úszó hőmérséklet , úszó páratartalom , belső nyomás ) {
this . hőmérséklet = hőmérséklet ;
ezt . páratartalom = páratartalom ;
ezt . nyomás = nyomás ;
notifyObservers ();
}
}
class CurrentConditionsDisplay implements Observer {
private float temperature ;
privát úszó páratartalom ;
privát int nyomás ;
@Public
void frissítés felülbírálása ( lebegő hőmérséklet , úszó páratartalom , belső nyomás ) { this . hőmérséklet = hőmérséklet ; ezt . páratartalom = páratartalom ; ezt . nyomás = nyomás ; kijelző (); }
public void display () {
Rendszer . ki . printf ( "Most az értékek: %.1f Celsius fok és %.1f %% páratartalom. Nyomás %d Hgmm\n" , hőmérséklet , páratartalom , nyomás );
}
}
Forrásszöveg C++ nyelven
#include <iostream>
#include <karakterlánc>
#include <list>
névtér használata std ;
osztály FelügyeltString ;
osztályú IObserver
{
nyilvános :
virtual void handleEvent ( const FelügyeltString & ) = 0 ;
};
class SupervisedString // Megfigyelhető osztály {
string_str ; _
lista < IObserver *> _observers ;
érvénytelen _Értesítés ()
{
for ( auto & megfigyelő : _observers )
{
megfigyelő -> handleEvent ( * this );
}
}
nyilvános :
érvénytelen hozzáadás ( IObserver & ref )
{
_megfigyelők . push_back ( & ref );
}
érvénytelen eltávolítás ( IObserver & ref )
{
_megfigyelők . eltávolítás ( & ref );
}
const string & get () const
{
return_str ; _
}
void reset ( string str )
{
_str = str ;
_Értesítés ();
}
};
class Reflector : public IObserver // A megfigyelt karakterláncot kiírja cout {
nyilvános :
virtuális void handleEvent ( const SupervisedString & ref )
{
cout << ref . get () << endl ;
}
};
class Számláló : public IObserver // Kiírja a megfigyelt karakterlánc hosszát cout {
nyilvános :
virtuális void handleEvent ( const SupervisedString & ref )
{
cout << "length = " << ref . kap (). hossz () << endl ;
}
};
int main ()
{
FelügyeltString str ;
reflektor refl ;
Számláló cnt ;
str . add ( refl );
str . reset ( "Hello, World!" );
cout << endl ;
str . eltávolítani ( refl );
str . add ( cnt );
str . reset ( "Világ, helló!" );
cout << endl ;
return 0 ;
}
Forrásszöveg az ActionScriptben
//fájl IObserver.as
package
{
public interface IObserver
{
function notify ( obj : Object ): void ;
}
}
//fájl ExchangeRate.as
package
{
public class Árfolyamérték
{
private static var _instance : ExchangeRate = null ;
private var megfigyelők : Array = [];
private var _exchangeRate : Objektum ;
public function ExchangeRate ()
{
if ( _instance == null ) throw new Error ( 'Model Singleton!' );
}
public static function getInstance (): ExchangeRate
{
if ( _instance == null ) _instance = new ExchangeRate ();
return _instance ;
}
public function get exchangeRate (): Object
{
return _exchangeRate ;
}
public function set exchangeRate ( érték : Object ): void
{
_exchangeRate = érték ;
ezt . notifyObservers ();
}
public function registerObserver ( érték : IObserver ): void
{
this . megfigyelők . push ( érték );
}
private function notifyObservers ( ) : void
{
for every ( var megfigyelő : IObserver ebben . megfigyelők ) { megfigyelő . értesíteni ( ezt ); } } } }
//file ProductItem.as
package
{
public class ProductItem implements IObserver
{
public function ProductItem ()
{
ExchangeRate . getInstance (). registerObserver ( ez );
}
public function notify ( érték : objektum ) : void
{
if ( az érték ExchangeRate ) { var Exchange : ExchangeRate = Árfolyam értéke ; nyomkövetés ( Exchange.exchangeRate ) ; _ } } } }
//fájl Main.as
package
{
import flash.display.Sprite ;
public class Main extends Sprite
{
public function Main (): void
{
var item1 : ProductItem = new ProductItem ();
var item2 : ProductItem = new ProductItem ();
Árfolyam . getInstance (). árfolyam = 3,5 ;
}
}
}
Forrásszöveg VB.NET nyelven
Importálás System.Collections
Imports System.Threading
Névtér Megfigyelő
''' <összegzés>
''' Megfigyelő minta Judith Bishop 2007. jan.
'''
''' Az alany egy szálban fut, és függetlenül változtatja állapotát
''''. Minden változásnál értesíti a Megfigyelőit.
'''' </summary>
Osztály Program
Megosztott alfő ( ) Halvány tárgy új témaként ( ) Halvány megfigyelő új megfigyelőként ( tárgy , " Közép " , vbTab & vbTab ) Halvány megfigyelő2 Új megfigyelőként ( tárgy , "Jobb" , vbTab & vbTab & vbTab & vbTab ) tárgy . menj ()
Várja meg a felhasználói
konzolt . Olvassa el ()
End Sub
végi osztály
Az osztályszimulátor IEnumerable
privát mozgásokat valósít meg karakterláncként ( ) = { "5" , "3" , "1" , "6" , "7" }
Nyilvános függvény GetEnumerator () Ahogy az IEnumerator megvalósítja az IEnumerable -t . GetEnumerator
Return lépések . GetEnumerator ' //
Hozamvégi függvény
végosztálya
Osztály alany
nyilvános delegált alhívás ( ByVal s As String ) _
Nyilvános eseményértesítés visszahívásként Privát szimulátor új szimulátorként ( ) Privát m_SubjectState karakterláncként Privát Const sebesség egész számként = 200 _ _ _
Public Property SubjectState () As String
Get
Return m_SubjectState
End Get
Set ( ByVal érték As String )
m_SubjectState = érték
End Set
End Tulajdonság
Nyilvános Sub Go ()
Hívás ( Új szál ( New ThreadStart ( AddressOf Run ))). Kezdés ()
Vége Sub
Privát alfutás ( ) Minden s karakterláncként szimulátorkonzolban . _ _ _ _ WriteLine ( "Tárgy: " & s ) SubjectState = s RaiseEvent Notify ( s ) ' ezredmásodperc Thread . Alvás ( sebesség ) Következő End Sub End Class
Interfész IObserver
Sub Update ( ByVal állapot As String )
End Interface
Class Observer
Az IObservert valósítja meg
Privát név Karakterláncként Privát tárgy Tárgyként Privát állapot Karakterláncként Privát rés Karakterláncként _ _ _ _
Public Sub New ( ByVal tárgy As Subject , ByVal név As String , ByVal gap As String )
Me . tárgy = tárgy
Én . név = név
Én . rés = hézag
AddHandler tárgy . Értesítés , AddressOf Update
End Sub
Nyilvános alfrissítés ( ByVal subjectState As String ) Az IObservert valósítja meg . Állapot frissítése = tárgyStateConsole . _ WriteLine ( hézag & név & ": " & állapot ) End Sub End Class End névtér
Forráskód Pythonban
abc importból ABCMeta , abstractmethod _
osztály megfigyelő ( metaosztály = ABCMeta ):
"""
Absztrakt megfigyelő
"""
@abstractmethod
def update ( self , message : str ) -> None :
"""
Get new message
"""
pass
osztály Megfigyelhető ( metaclass = ABCMeta ):
"""
Absztrakt megfigyelhető
"""
def __init__ ( self ) -> None :
"""
Konstruktor.
"""
self . megfigyelők = [] # a megfigyelők listájának inicializálása
def register ( self , megfigyelő : Megfigyelő ) -> None :
""" Új megfigyelő regisztrálása
""" self feliratkozáshoz
. megfigyelők . hozzáfűz ( megfigyelő )
def notify_observers ( self , message : str ) -> None :
"""
Üzenet küldése minden olyan megfigyelőnek, aki feliratkozott a
""" megfigyelhető osztály adott objektumának eseményeire
az önmagában megfigyelő számára . megfigyelők : megfigyelő . frissítés ( üzenet )
osztály Újság ( Megfigyelhető ):
"""
Több ezer ember által követett újság
"""
def add_news ( self , news : str ) -> None :
""" Új hírközlés
"
""
self . notify_observers ( hírek )
osztályú polgár ( Figyelő ):
"""
Egy hétköznapi polgár, aki szereti reggelente olvasni kedvenc újságját
"""
def __init__ ( self , name : str ) -> None :
"""
Konstruktor.
:param név: az állampolgár neve , nehogy összetévessze valaki mással """
self .name = név
def update ( self , message : str ) -> None :
"""
A következő hír beszerzése
"""
print ( f ' { self . name } a következőket tanulta: { üzenet } ' )
if __name__ == '__main__' :
newspaper = Újság () # hozzon létre egy kis
újságot . register ( Citizen ( 'Ivan' )) # adj hozzá két újságos embert
. regisztráció ( Polgár ( 'Vaszilij' )) # ... rendszeresen előfizetik # ... és bedobunk egy másik újság kacsa újságot . add_news ( 'Megfigyelő - Viselkedési tervezési minta' )
''
Iván a következőket tanulta: Megfigyelő - Viselkedési tervezési minta
Vaszilij a következőket tanulta: Megfigyelő - Viselkedési tervezési minta
'''
Forrásszöveg Object Pascalban (Delphi)
programfigyelő ; _ /// Observer Pattern Judith Bishop 2007. jan. /// Pascalra portolta Dmitry Boyarintsev, 2018. május /// /// Az alany egy szálban fut, és /// függetlenül változtatja állapotát . Minden változásnál értesíti a Megfigyelőit.
{$ifdef fpc}{$mode delphi}{$H+}{$endif}
SysUtils , Classes ; _
típus
TBaseObserver = osztály ( TObject )
eljárás Frissítés ( const astate : string ) ; virtuális ; absztrakt ;
vége ;
TBaseSubject = osztály ( TObject )
eljárás AddObserver ( aobserver : TBaseObserver ) ; virtuális ; absztrakt ;
eljárás RemoveObserver ( aobserver : TBaseObserver ) ; virtuális ; absztrakt ;
eljárás NotifyObservers ( const s : string ) ; virtuális ; absztrakt ;
vége ;
típus
{ TSubject }
TSubject = osztály ( TBaseSubject )
privát
fObszerverek : TLista ;
fSzimulátor : TStringList ;
sebesség : Integer ;
védett
eljárás Futtatás ;
public
konstruktor Létrehozás ;
destructor Elpusztítani ; felülbírálni ;
eljárás AddObserver ( aobserver : TBaseObserver ) ; felülbírálni ;
eljárás RemoveObserver ( aobserver : TBaseObserver ) ; felülbírálni ;
eljárás NotifyObservers ( konst állapot : string ) ; felülbírálni ;
eljárás Go ;
vége ;
TObserver = osztály ( TBaseObserver )
private
fname : string ;
fsubject : TBaseSubject ;
fstate : string_ _
fgap : string_ _
public
konstruktor Create ( abject : TBaseSubject ; const aname , agap : string ) ;
procedúra Frissítés ( const astate : string ) ; felülbírálni ;
vége ;
{ TSubject }
eljárás TSubject . futni ;
var
i : integer ;
s : string_ _
start for i := 0 az fSimulatorhoz
. Count - 1 do begin s := fSimulator [ i ] ; Writeln ( 'Tárgy: ' , s ) ; NotifyObservers ( ek ) ; Alvás ( sebesség ) ; // ezredmásodperc vége ; vége ;
konstruktor TSubject . létrehozni ;
begin
inherited Create ;
fObservers := TLista . létrehozni ;
sebesség := 200 ;
fSimulator := TStringList . létrehozni ;
fSzimulátor . AddStrings ([ '5' , '3' , '1' , '6' , '7' ]) ;
vége ;
destructor TSubject . elpusztítani ;
indítsa el
a fObservers-t . Ingyenes ;
fSzimulátor . Ingyenes ;
vége ;
eljárás TSubject . AddObserver ( megfigyelő : TBaseObserver ) ;
indítsa el
a fObservers-t . Add ( aobserver ) ;
vége ;
eljárás TSubject . RemoveObserver ( megfigyelő : TBaseObserver ) ;
indítsa el
a fObservers-t . Eltávolítás ( aobserver ) ;
vége ;
eljárás TSubject . NotifyObservers ( const astate : string ) ;
var
i : integer ;
Kezdje az i := 0 -hoz az fObservershez
. Számlálás - 1 do TBaseObserver ( fObservers [ i ]) . Frissítés ( astate ) ; vége ;
típus
{ TMethodThread }
TMethodThread = osztály ( TThread )
védett
fMethod : TThreadMethod ;
eljárás Végrehajtás ; felülbírálni ;
public
konstruktor Create ( AMethod : TThreadMethod ) ;
vége ;
{ TMethodThread }
konstruktor TMethodThread . Létrehozás ( AMethod : TThreadMethod ) ;
begin
fMethod := AMethod ;
FreeOnTerminate := Igaz ;
öröklött Létrehozás ( hamis ) ;
vége ;
eljárás TMethodThread . Végrehajtás ;
kezdődik
, ha Assigned ( fMethod ) then fMethod () ;
vége ;
eljárás TSubject . menj ;
kezdje el
a TMethodThread programot . Létrehoz ( Self.Run ) ; _ _ vége ;
konstruktor TObserver . Create ( asubject : TBaseSubject ; const aname , agap : string ) ;
begin
inherited Create ;
fsubject := alattject ;
fname := név ;
fgap := agap ;
ha Assigned ( fsubject ) akkor fsubject . AddObserver ( saját ) ;
vége ;
eljárás TObserver . Frissítés ( const astate : string ) ;
begin
fstate := astate ;
writeln ( fgap , fname , ':' , állapot ) ;
vége ;
/// Fő program
var
tárgy : TSubject ;
megfigyelő : TObserver ;
megfigyelő2 : TOmegfigyelő ;
beginsubject
: = TSubject . létrehozni ; megfigyelő := TObserver . Létrehoz ( tárgy , 'Közép' , #9#9 ) ; megfigyelő2 := TOmegfigyelő . Létrehozása ( tárgy , 'Jobb' , #9#9#9#9 ) ; próbáld ki a témát . menj () ; // Várja meg a readln felhasználót ; végre megfigyelő . Ingyenes ; megfigyelő2 . Ingyenes ; tárgy . Ingyenes ; vége ; vége .
Ruby forráskód
modul Megfigyelhető
def inicializálás
@observers = []
vége
def add_observer ( megfigyelő )
@observers << megfigyelő , hacsak nem @observers . tartalmazza? ( megfigyelő )
vége
def delete_observer ( megfigyelő )
@observers . törlés ( megfigyelő )
vége
def notify_observers
@observers . mindegyik { | x | x . frissítés ( self )}
end
end
osztály Munkavállalói
közé tartozik Megfigyelhető
attr_reader :name
attr_accessor :title , :fizetés
def inicializálás ( név , beosztás , fizetés )
szuper ( )
@ név = név @
cím = cím
@fizetés = fizetés
vége
vége
osztály BaseObserver
def update lift 'Meg kell valósítani
a "frissítési" funkciót'
end
end
class Bérszámfejtés < BaseObserver
def update ( alkalmazott )
p ( "Új csekk kivágása #{ alkalmazott . neve } !" )
p ( " A fizetése most #{ alkalmazott . fizetés } !" )
end
end
osztály TaxMan < BaseObserver
def update ( alkalmazott )
p ( "Küldj #{ alkalmazott . neve } új adószámlát!" )
end
end
mike = Alkalmazott . új ( 'Mike' , 'projektmanger' , 25000 )
Mike . add_observer ( Bérszámfejtés . új )
mike . add_observer ( TaxMan . új )
Mike . fizetés = 35000
mike . title = 'vezető projektmenedzser'
mike . notify_observers
=begin
A
"Vágjon új csekket Mike-nak!"
"Most 35000 a fizetése!"
– Küldj új adószámlát Mike-nak!
=vége
Forráskód Rustban
/// A példa leírja, hogyan lehet adatokat fogadni egy meteorológiai állomástól (WeatherData szerkezet, esemény diszpécser) és
/// használni a képernyőn való megjelenítéséhez (CurrentConditionsDisplay szerkezet, eseményfigyelő).
/// A figyelőt a register_observer metódussal regisztráljuk a megfigyelővel, amely egy lezárást végez és
/// hozzáadja a megfigyelők listájához. Amikor az időjárási adatok megváltoznak, a notify_observers metódus meghívódik, amely
/// bezárja az összes figyelőt, átadva nekik a frissített adatokat.
használja std :: rc :: Rc ;
std használata :: cella :: RefCell ;
típus ObserverFn = Box < dyn Fn ( f32 , f32 , i32 ) > ;
Megfigyelhető tulajdonság {
fn register_observer ( & mut self , o : ObserverFn ) -> usize ;
fn remove_observer ( & mut self , idx : usize );
fn notify_observers ( & mut self );
}
#[derive (alapértelmezett)]
struct WeatherData {
megfigyelők : Vec < ObserverFn > ,
hőmérséklet : f32 ,
páratartalom : f32 ,
nyomás : i32 ,
}
impl Időjárásadatok {
fn set_measurements ( & mut self , hőmérséklet : f32 , páratartalom : f32 , nyomás : i32 ) {
önmaga . hőmérséklet = hőmérséklet ;
önmaga . páratartalom = páratartalom ;
önmaga . nyomás = nyomás ;
önmaga . notify_observers ();
}
}
impl Megfigyelhető időjárási adatokhoz {
fn register_observer ( & mut self , o : ObserverFn ) -> usize {
önmaga . megfigyelők . nyomni ( o );
önmaga . megfigyelők . len () - 1
}
fn remove_observer ( & mut self , idx : usize ) {
önmaga . megfigyelők . eltávolítás ( idx );
}
fn notify_observers ( & mut self ) {
önmagában megfigyelő számára . _ megfigyelők . iter () {
( * megfigyelő )( saját . hőmérséklet , saját . páratartalom , saját . nyomás );
}
}
}
#[derive (alapértelmezett)]
struct CurrentConditionsDisplay {
hőmérséklet : f32 ,
páratartalom : f32 ,
nyomás : i32 ,
}
impl CurrentConditionsDisplay {
fn display ( & self ) {
println! ( "Most az értékek: {:.1} Celsius-fok és {:.1} % páratartalom. Nyomás {} Hgmm." ,
önmaga . hőmérséklet , önmaga . páratartalom , önmaga . nyomás );
}
fn frissítés ( & mut self , hőmérséklet : f32 , páratartalom : f32 , nyomás : i32 ) {
önmaga . hőmérséklet = hőmérséklet ;
önmaga . páratartalom = páratartalom ;
önmaga . nyomás = nyomás ;
önmaga . kijelző ();
}
}
fn main () {
let mut weather_data = Időjárási adatok :: alapértelmezett ();
let current_display = Rc :: new ( RefCell :: new ( CurrentConditionsDisplay :: default ()));
let megfigyelő = aktuális_megjelenítés . klón ();
weather_data . register_observer ( Box :: new ( mozgás | t , h , p | megfigyelő . kölcsön_mut (). update ( 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 forráskód
# Egy példa teljesen megegyezik a fentivel a Pythonban
Observer := Objektum klón
Megfigyelhető := List klón do (
regiszter := getSlot ( "push" )
notify := method ( üzenet , saját foreach ( megfigyelő , megfigyelő frissítés ( üzenet )))
)
Newspaper := Megfigyelhető klón do ( addNews := metódus ( hír , értesíteni ( hír )))
Citizen := Observer clone do (
create := metódus ( név , önklón lexicalDo ( név := név )) update := metódus ( üzenet , writeln ( név .. " megtudta: " .. üzenet ) ) )
újság : = Újságklón
újság do (
regiszter ( Citizen create ( "Ivan" ) ))
regisztrál ( Citizen create ( "Vaszilij" ))
addNews ( "Observer - Behavioral Design Pattern" )
)
#>>>> Iván a következőket tanulta: A megfigyelő egy viselkedési tervezési minta
#>>>> Vaszilij megtanulta a következőket: A megfigyelő egy viselkedési tervezési minta
Forrásszöveg javascriptben
class Megfigyelhető {
konstruktor () {
this . hallgatók = {};
}
// Iratkozz fel.
on ( e , visszahívás ) {
if ( this . hallgatók [ e ] == undefined ) {
this . hallgatók [ e ] = {};
ezt . hallgatók [ e ]. eventProperty = {};
ezt . hallgatók [ e ]. eventProperty . isOnOnce = false ;
ezt . hallgatók [ e ]. adat = [];
}
ezt . hallgatók [ e ]. adatok . push ( visszahívás );
}
// Iratkozz fel egyszer.
onOnce ( e , visszahívás ) {
this . on ( e , visszahívás );
ezt . hallgatók [ e ]. eventProperty . isOnOnce = igaz ;
}
// Leiratkozás.
off ( e , visszahívás ) {
this . hallgatók [ e ]. adat = ez . hallgatók [ e ]. adatok .
filter ( function ( figyelő ) { return hallgató !== visszahívás ; });
}
// Üzenet küldése az előfizetőknek.
emit ( e , adat ) {
if ( ez . hallgatók [ e ] == undefined || this . hallgatók [ e ]. adat == undefined ) {
return ;
}
let itObj = ez ;
ezt . hallgatók [ e ]. adatok . forEach ( hallgató => {
if ( itObj . hallgatók [ e ]. eventProperty . isOnOnce ) {
itObj . off ( e , itObj . hallgatók [ e ]. adatok [ 0 ]);
}
figyelő ( adat );
});
}
}
További információk
A .NET Framework 4.0 -ban a megfigyelő tervezési mintája általános interfészek System.IObservable<T>és System.IObserver<T>[2] megvalósításával valósul meg .
Irodalom
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides . Objektumorientált tervezés technikái. Tervezési minták = Design Patterns. Az újrafelhasználható objektum-orientált szoftver elemei. - Szentpétervár. : Péter, 2009. - 366 p. - ISBN 978-5-469-01136-1 .
- Eric Freeman, Elizabeth Freeman. Tervezési minták = Head First Design Patterns. - Szentpétervár. : Péter, 2011. - 656 p. - ISBN 978-5-459-00435-9 .
Jegyzetek
- ↑ Megfigyelő minta . Letöltve: 2013. június 13. Az eredetiből archiválva : 2013. június 13.. (határozatlan)
- ↑ 1 2 Megfigyelő tervezési minta . Letöltve: 2013. június 13. Az eredetiből archiválva : 2013. június 13.. (határozatlan)
- ↑ Megfigyelő minta . Letöltve: 2019. november 4. Az eredetiből archiválva : 2019. november 4.. (határozatlan)