Observador (patrón de diseño)

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 19 de mayo de 2019; las comprobaciones requieren 15 ediciones .
Observador
Observador
Tipo de conductual
Objetivo
  • El patrón Observer define una dependencia de uno a muchos entre objetos, de modo que cuando cambia el estado de un objeto, todos los objetos que dependen de él se notifican y actualizan automáticamente;
  • El patrón del Observador encapsula el componente principal (independiente) en la abstracción del Sujeto y los componentes mutables (dependientes) en la jerarquía del Observador;
  • El patrón Observer define la parte "Vista" de un modelo Modelo-Vista-Controlador (MVC) [1] .
Descrito en Patrones de diseño

El  observador es un patrón de diseño de comportamiento . También conocido como "subordinados" ( ing. Dependientes ). Implementa un mecanismo de clase que permite que un objeto de esta clase reciba notificaciones sobre cambios en el estado de otros objetos y así observarlos [2] .  

Las clases a cuyos eventos se suscriben otras clases se denominan Sujetos, y las clases suscriptoras se denominan Observadores [ 3 ] . 

Plantillas similares: " editor-suscriptor ", " intermediario ", " solitario ".

Cita

Define una dependencia de uno a muchos entre objetos, de modo que cuando cambia el estado de un objeto, se notifica el evento a todos los que dependen de él.

Implementación

Al implementar el patrón de observador, las siguientes clases se usan comúnmente:

Alcance

El patrón observador se utiliza cuando el sistema tiene las siguientes propiedades:

Este patrón se usa a menudo en situaciones en las que el remitente de los mensajes no está interesado en lo que hacen los destinatarios con la información que se les proporciona.

Ejemplos

PHP5 (SPL)

Texto fuente en lenguaje php /** * PHP proporciona soporte integrado para este patrón a través de la extensión * SPL (Biblioteca PHP estándar) incluida: * SplObserver - interfaz para Observer (observador), * SplSubject - interfaz de Observable (observable), * SplObjectStorage - clase auxiliar (Proporciona mejoras para guardar y eliminar * objetos, en particular, se implementan los métodos Attach() y Detach()). */ class Observable implementa SplSubject { private $storage ; function __construct () { $this -> storage = new SplObjectStorage (); } función adjuntar ( SplObserver $observador ) { $esto -> almacenamiento -> adjuntar ( $observador ); } función separar ( SplObserver $ observador ) { $ esto -> almacenamiento -> separar ( $ observador ); } function notificar () { foreach ( $this -> almacenamiento como $obj ) { $obj -> actualizar ( $this ); } } } class ConcreteObserver implementa SplObserver { private $observable ; privado $índice ; function __construct ( Observable $observable ) { static $sindex = 0 ; $esto -> índice = $síndice ++ ; $esto -> observable = $observable ; $observable -> adjuntar ( $this ); } actualización de la función ( SplSubject $subject ) { if ( $subject === $this -> observable ) { echo "Enviar notificación a ConcreteObserver [ $this->index ] \n " ; } } } $observable = nuevo Observable (); nuevo ConcreteObserver ( $observable ); nuevo ConcreteObserver ( $observable ); nuevo ConcreteObserver ( $observable ); $observable -> notificar ();

PHP5

Texto fuente en lenguaje php interfaz Observer { función notificar ( $obj ); } class ExchangeRate { static private $instancia = NULL ; $observadores privados = matriz (); tipo de cambio privado $ ; función privada __construcción () {} función privada __clon () {} función pública estática getInstance () { if ( self :: $instancia == NULL ) { self :: $instancia = new ExchangeRate (); } return self :: $instancia ; } public function getExchangeRate () { return $this -> exchange_rate ; } public function setExchangeRate ( $new_rate ) { $this -> exchange_rate = $new_rate ; $esto -> notificarObservadores (); } public function registerObserver ( Observer $obj ) { $this -> observers [] = $obj ; } function notificarObservadores () { foreach ( $esto -> observadores como $obj ) { $obj -> notificar ( $esto ); } } } clase ProductItem implementa Observer { public function __construct () { ExchangeRate :: getInstance () -> registerObserver ( $this ); } notificación de función pública ( $obj ) { if ( $obj instancia de ExchangeRate ) { // Actualizar datos de tasa de cambio print "¡Actualización recibida! \n " ; } } } $producto1 = nuevo ProductoItem (); $producto2 = nuevo artículo de producto (); ExchangeRate :: getInstance () -> setExchangeRate ( 4.5 );

C#

Texto fuente en C# utilizando el sistema ; utilizando System.Collections ; usando System.Collections.Generic ; utilizando System.Threading ; namespace Observer { /// <summary> /// Observer Pattern Judith Bishop enero de 2007 /// Actualizado por Kobel' Bohdan 2013 /// /// El sujeto se ejecuta en un subproceso y cambia su estado /// de forma independiente. En cada cambio, notifica a sus Observadores. /// </summary> class Program { static void Main ( string [] args ) { Asunto asunto = nuevo Asunto (); Observador observador = nuevo Observador ( sujeto , "Centro" , "\t\t" ); Observador observador2 = nuevo Observador ( sujeto , "Derecha" , "\t\t\t\t" ); sujeto _ ir (); // Esperar a la Consola del usuario . leer (); } } Simulador de clase : IEnumerable { cadena [] movimientos = { "5" , "3" , "1" , "6" , "7" }; IEnumerator público GetEnumerator () { foreach ( elemento de cadena en movimientos ) elemento de retorno de rendimiento ; } } interfaz ISubject { void AddObserver ( observador IObserver ); void RemoveObserver ( IObserver observador ); void NotifyObservers ( cadena s ); } class Asunto : ISubject { public string SubjectState { get ; conjunto ; } Public List < IObserver > Observadores { get ; conjunto privado ; } simulador de simulador privado ; velocidad interna constante privada = 200 ; public Subject () { Observers = new List < IObserver >(); simulador = nuevo simulador (); } public void AddObserver ( observador de IObserver ) { Observadores . Agregar ( observador ); } public void RemoveObserver ( observador de IObserver ) { Observadores . Quitar ( observador ); } public void NotifyObservers ( string s ) { foreach ( var observador en Observadores ) { observador . Actualización ( es ); } } public void Ir () { hilo nuevo ( nuevo ThreadStart ( Ejecutar )). Inicio ( ); } void Ejecutar () { foreach ( cadena s en el simulador ) { Consola . WriteLine ( "Asunto:" + s ); Estado del Sujeto = s ; Notificar a los observadores ( s ); hilo _ dormir ( velocidad ); // milisegundos } } } interfaz IObserver { void Update ( estado de cadena ); } observador de clase : IObserver { nombre de cadena ; ISujeto sujeto ; estado de la cadena ; brecha de cuerda ; public Observer ( sujeto ISubject , nombre de cadena , espacio de cadena ) { this . sujeto = sujeto ; esto _ nombre = nombre ; esto _ brecha = brecha ; sujeto _ AddObserver ( esto ); } Public void Update ( string subjectState ) { state = subjectState ; consola _ WriteLine ( brecha + nombre + ":" + estado ); } } }

Java

Fuente Java // El ejemplo describe cómo recibir datos de una estación meteorológica (clase WeatherData, despachador de eventos) y //utilizarlos para mostrarlos en la pantalla (clase CurrentConditionsDisplay, detector de eventos). //El oyente se registra con el observador usando el método registerObserver (en este caso, el oyente se agrega a la lista de observadores). //El registro ocurre en el momento en que se crea el objeto currentDisplay, porque el método registerObserver se aplica en el constructor. //Cuando los datos meteorológicos cambian, se llama al método de notificaciónObservers, que a su vez llama al método de actualización //en todos los oyentes, pasándoles los datos actualizados. importar java.util.LinkedList ; importar java.util.List ; Estación meteorológica de clase pública { public static void main ( String [] args ) { WeatherData weatherData = new WeatherData (); Observador currentDisplay = new CurrentConditionsDisplay (); datos meteorológicos . RegisterObserver ( presentación actual ); datos meteorológicos . establecerMedidas ( 29 f , 65 f , 745 ); datos meteorológicos . establecer medidas ( 39 f , 70 f , 760 ); datos meteorológicos . establecerMedidas ( 42 f , 72 f , 763 ); } } interfaz Observer { actualización nula ( temperatura de flotación , humedad de flotación , presión interna ); } interfaz Observable { void registerObserver ( Observer o ); void removeObserver ( Observador o ); void notificarObservadores (); } class WeatherData implementa Observable { private List < Observador > observadores ; temperatura del flotador privado ; humedad del flotador privado ; presión interna privada ; Public WeatherData () { observadores = nueva LinkedList <> (); } @Override public void registerObserver ( Observador o ) { observadores . añadir ( o ); } @Override public void removeObserver ( Observador o ) { observadores . quitar ( o ); } @Override public void notificarObservadores () { para ( Observador observador : observadores ) observador . actualización ( temperatura , humedad , presión ); } public void setMeasurements ( temperatura de flotación , humedad de flotación , presión interna ) { this . temperatura = temperatura ; esto _ humedad = humedad ; esto _ presión = presión ; notificar a los observadores (); } } class CurrentConditionsDisplay implementa Observer { temperatura flotante privada ; humedad del flotador privado ; presión interna privada ; @Override public void update ( temperatura de flotación , humedad de flotación , presión interna ) { this . temperatura = temperatura ; esto _ humedad = humedad ; esto _ presión = presión ; mostrar (); } pantalla de vacío público () { System . fuera _ printf ( "Ahora los valores son: %.1f grados Celsius y %.1f %% humedad. Presión %d mmHg\n" , temperatura , humedad , presión ); } }

C++

Texto fuente en C++ #incluir <iostream> #incluir <cadena> #incluir <lista> utilizando el espacio de nombres estándar ; clase cadena supervisada ; clase IObserver { público : virtual void handleEvent ( const SupervisedString & ) = 0 ; }; class SupervisedString // Clase observable { cadena_cadena ; _ list < IObserver *> _observadores ; vacío _Notificar () { para ( auto y observador : _observadores ) { observador -> handleEvent ( * esto ); } } público : anular agregar ( IObserver & ref ) { _observadores . retroceder ( & ref ); } anular eliminar ( IObserver & ref ) { _observadores . eliminar ( & ref ); } const cadena & obtener () const { cadena_retorno ; _ } reinicio vacío ( cadena str ) { _cadena = cadena ; _Notificar (); } }; class Reflector : public IObserver // Imprime la cadena observada en cout { público : virtual void handleEvent ( const SupervisedString & ref ) { cout << referencia . obtener () << endl ; } }; class Counter : public IObserver // Imprime la longitud de la cadena observada en cout { público : virtual void handleEvent ( const SupervisedString & ref ) { cout << "longitud = " << ref . obtener (). longitud () << endl ; } }; int principal () { SupervisedString str ; reflector reflector ; Contador cnt ; calle _ añadir ( refl ); calle _ reset ( "¡Hola, mundo!" ); cout << endl ; calle _ eliminar ( refl ); calle _ agregar ( cnt ); calle _ reset ( "Mundo, ¡Hola!" ); cout << endl ; devolver 0 ; }

ActionScript

Texto de origen en ActionScript //archivo IObserver.as paquete { interfaz pública IObserver { función de notificación ( obj : Object ): void ; } } //file ExchangeRate.as paquete { public class ExchangeRate { private static var _instance : ExchangeRate = null ; observadores privados de var : Array = []; privado var _exchangeRate : Objeto ; public function ExchangeRate () { if ( _instance == null ) arroja un nuevo error ( 'Model Singleton!' ); } función estática pública getInstance (): ExchangeRate { if ( _instance == null ) _instance = new ExchangeRate (); volver _instancia ; } función pública obtener tasa de cambio (): Objeto { return _tasa de cambio ; } función pública establecer tasa de cambio ( valor : objeto ): vacío { _tasa de cambio = valor ; esto _ notificar a los observadores (); } función pública registerObserver ( valor : IObserver ): void { this . observadores _ empujar ( valor ); } función privada notificarObservadores (): void { para cada ( var observador : IObserver en este . observadores ) { observador . notificar ( esto ); } } } } //file ProductItem.as paquete { public class ProductItem implements IObserver { public function ProductItem () { ExchangeRate . obtenerInstancia (). registroObservador ( esto ); } notificación de función pública ( valor : Objeto ): void { if ( el valor es ExchangeRate ) { var exchange : ExchangeRate = value as ExchangeRate ; rastrear ( cambio.tasacambio ) ; _ } } } } //archivo Main.as paquete { import flash.display.Sprite ; public class Main extiende Sprite { public function Main (): void { var item1 : ProductItem = new ProductItem (); var item2 : ProductItem = new ProductItem (); tipo de cambio . obtenerInstancia (). tipo de cambio = 3.5 ; } } }

VB.NET

Texto fuente en lenguaje VB.NET Importaciones System.Collections Importaciones System.Threading Namespace Observer ''' <summary> ''' Observer Pattern Judith Bishop Jan 2007 ''' ''' El sujeto se ejecuta en un subproceso y cambia su estado ''' de forma independiente. En cada cambio, notifica a sus Observadores. ''' </summary> Clase Programa Compartido Sub Principal () Dim sujeto Como nuevo sujeto () Dim Observador Como nuevo observador ( sujeto , "Centro" , vbTab & vbTab ) Dim observador2 Como nuevo observador ( sujeto , "Derecha" , vbTab & vbTab & vbTab & vbTab ) asunto . ir () 'Esperar a la Consola del usuario . Leer () Fin sub clase final Class Simulator implementa movimientos privados IEnumerables como String () = { "5" , "3" , "1" , "6" , "7" } Función pública GetEnumerator () como IEnumerator implementa IEnumerable . GetEnumerator Retorno de movimientos . GetEnumerator ' // Función final de rendimiento Clase final Devolución de llamada secundaria de delegado público de asunto de clase ( ByVal s As String ) Public Event Notify As Callback Private simulator As New Simulator () Private m_SubjectState As String Private Const speed As Integer = 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 ))). Inicio () Fin Sub Ejecución secundaria privada () para cada s como cadena en la consola del simulador . WriteLine ( "Asunto:" & s ) SubjectState = s RaiseEvent Notify ( s ) ' milisegundos Subproceso . Dormir ( velocidad ) Siguiente Fin Sub Fin Clase Interfaz Actualización secundaria de IObserver ( estado ByVal como cadena ) Interfaz final Class Observer implementa IObserver Nombre privado As String Asunto privado As Asunto Estado privado As String Brecha privada As String Public Sub New ( sujeto de ByVal como asunto , nombre de ByVal como cadena , brecha de ByVal como cadena ) Yo . sujeto = sujeto Yo . nombre = nombrame . _ gap = gap AddHandler sujeto . Notificar , dirección de actualización End Sub Public Sub Update ( ByVal subjectState As String ) Implementa IObserver . Actualizar estado = subjectStateConsole ._ _ WriteLine ( brecha & nombre & ":" & estado ) End Sub End Class End Namespace

Pitón

Código fuente en Python de abc import ABCMeta , método abstracto clase Observador ( metaclase = ABCMeta ): """ Observador abstracto """ @abstractmethod def update ( self , mensaje : str ) -> Ninguno : """ Obtener nuevo mensaje """ pasar clase Observable ( metaclase = ABCMeta ): """ Resumen observable """ def __init__ ( self ) -> Ninguno : """ Constructor. """ self . observadores = [] # inicialización de la lista de observadores def registrarse ( self , observador : observador ) -> Ninguno : """ Registrar un nuevo observador para suscribirse """ self . observadores _ agregar ( observador ) def notificar_observadores ( self , mensaje : str ) -> Ninguno : """ Enviar un mensaje a todos los observadores suscritos a los eventos del objeto dado de la clase observable """ para el observador en sí mismo . observadores : observador . actualizar ( mensaje ) clase Periódico ( Observable ): """ Un periódico que es seguido por miles de personas """ def add_news ( self , news : str ) -> Ninguno : """ Nuevo comunicado de prensa """ self . notificar_observadores ( noticias ) class Citizen ( Observador ): """ Un ciudadano común al que le gusta leer su periódico favorito en la mañana """ def __init__ ( self , nombre : str ) -> Ninguno : """ Constructor. :param nombre: el nombre del ciudadano, para no confundirlo con otra persona """ self .name = nombre actualización def ( self , mensaje : str ) -> Ninguno : """ Obteniendo las próximas noticias """ print ( f ' { self . name } aprendió lo siguiente: { mensaje } ' ) if __name__ == '__principal__' : periodico = Periódico () # crear un periódico pequeño periódico . registrarse ( Ciudadano ( 'Ivan' )) # añadir dos personas que sean de diario . registrarse ( Ciudadano ( 'Vasily' )) # ... se suscribe regularmente # ... y lanzamos otro periódico pato periódico . add_news ( 'Observador - Patrón de diseño de comportamiento' ) ''' Ivan aprendió lo siguiente: Observer - Patrón de diseño de comportamiento Vasily aprendió lo siguiente: Observer - Patrón de diseño de comportamiento '''

ObjetoPascal

Texto fuente en Object Pascal (Delphi) observador del programa ; /// Patrón de observador Judith Bishop, enero de 2007 /// Adaptado a Pascal por Dmitry Boyarintsev, mayo de 2018 /// /// El sujeto se ejecuta en un subproceso y cambia su estado /// de forma independiente. En cada cambio, notifica a sus Observadores. {$ifdef fpc}{$modo delphi}{$H+}{$endif} utiliza SysUtils , Clases ; tipo TBaseObserver = class ( TObject ) procedimiento Actualizar ( const astate : string ) ; virtuales ; abstracto ; fin ; TBaseSubject = clase ( TObject ) procedimiento AddObserver ( aobserver : TBaseObserver ) ; virtuales ; abstracto ; procedimiento RemoveObserver ( aobserver : TBaseObserver ) ; virtuales ; abstracto ; procedimiento NotifyObservers ( const s : string ) ; virtuales ; abstracto ; fin ; escribe { Asunto } TSubject = class ( TBaseSubject ) fObservers privados : TList ; fSimulador : TStringList ; velocidad : Entero ; procedimiento protegido Ejecutar ; constructor público Crear ; destructor Destruir ; anular ; procedimiento AddObserver ( aobserver : TBaseObserver ) ; anular ; procedimiento RemoveObserver ( aobserver : TBaseObserver ) ; anular ; procedimiento NotifyObservers ( const astate : string ) ; anular ; procedimiento Ir ; fin ; TObserver = class ( TBaseObserver ) private fname : cadena ; fsubject : TBaseSubject ; festado : cadena _ fgap : cadena _ public constructor Create ( asubject : TBaseSubject ; const aname , agap : string ) ; Actualización del procedimiento ( const astate : string ) ; anular ; fin ; { Asunto } procedimiento TSubject . correr ; var i : entero ; s : cadena _ comenzar para i := 0 a fSimulator . Cuenta - 1 empieza s : = fSimulator [ i ] ; Writeln ( 'Asunto:' , s ) ; Notificar a los observadores ( s ) ; Dormir ( velocidad ) ; // fin de milisegundos ; fin ; constructor TSubject . crear ; comenzar heredado Create ; fObservadores := TList . crear ; velocidad := 200 ; fSimulador := TStringList . crear ; fSimulador . AddStrings ([ '5' , '3' , '1' , '6' , '7' ]) ; fin ; destructor TSubject . destruir ; comenzar fObservadores . Gratis ; fSimulador . Gratis ; fin ; procedimiento TSubject . AddObserver ( observador : TBaseObserver ) ; comenzar fObservadores . Añadir ( un observador ) ; fin ; procedimiento TSubject . RemoveObserver ( observador : TBaseObserver ) ; comenzar fObservadores . Eliminar ( un observador ) ; fin ; procedimiento TSubject . NotifyObservers ( const astate : string ) ; var i : entero ; comenzar para i := 0 a fObservers . Count - 1 do TBaseObserver ( fObservers [ i ]) . Actualizar ( un estado ) ; fin ; escribe { Subproceso de método } TMethodThread = clase ( TThread ) protegido fMethod : TThreadMethod ; procedimiento Ejecutar ; anular ; constructor público Create ( AMethod : TThreadMethod ) ; fin ; { Subproceso de método } constructor TMethodThread . Crear ( AMétodo : TThreadMethod ) ; comenzar fMethod := AMethod ; FreeOnTerminate := Verdadero ; heredado Crear ( falso ) ; fin ; procedimiento TMethodThread . ejecutar ; comenzar si está asignado ( fMethod ) luego fMethod ( ) ; fin ; procedimiento TSubject . ir ; comenzar TMethodThread . Crear ( Self.Run ) ; _ _ fin ; constructor TObserver . Create ( asubject : TBaseSubject ; const aname , agap : string ) ; comenzar heredado Create ; fsujeto := unsujeto ; fnombre := anombre ; fgap := agap ; si está asignado ( fsubject ) entonces fsubject . AddObserver ( auto ) ; fin ; procedimiento TObserver . Actualizar ( const astate : string ) ; comenzar festado := aestado ; writeln ( fgap , fname , ':' , astate ) ; fin ; /// Programa principal var asunto : TSubjeto ; observador : TObserver ; observador2 : TOobservador ; beginsubject : = TSubject . crear ; observador := TObserver . Crear ( asunto , 'Centro' , #9#9 ) ; observador2 := TOobservador . Crear ( asunto , 'Derecha' , #9#9#9#9 ) ; prueba el tema . ir () ; // Esperar al usuario readln ; finalmente observador . Gratis ; observador2 . Gratis ; sujeto _ Gratis ; fin ; fin _

Rubí

código fuente rubí módulo Observable def inicializar @observers = [] final def add_observer ( observador ) @observadores << observador a menos que @observadores . ¿incluir? ( observador ) fin def delete_observer ( observador ) @observadores . eliminar ( observador ) fin def notificar_observadores @observadores . cada { | x | x _ actualizar ( auto )} final final clase Empleado incluir Observable attr_reader :nombre attr_accessor :título , :salario def inicializar ( nombre , título , salario ) super () @nombre = nombre @ título = título @salario = salario fin fin class BaseObserver def update raise 'Debe implementarse la función "actualizar"' end end class Nómina < BaseObserver def update ( empleado ) p ( "¡Corte un nuevo cheque para #{ empleado . nombre } !" ) p ( "Su salario ahora es #{ empleado . salario } !" ) end end class TaxMan < BaseObserver def update ( empleado ) p ( "Enviar #{ empleado . nombre } una nueva factura de impuestos!" ) end end mike = empleado . nuevo ( 'Mike' , 'gerente de proyecto' , 25000 ) micro _ add_observer ( Nómina . nuevo ) mike . add_observer ( TaxMan . nuevo ) micro _ salario = 35000 micras . title = 'gerente sénior de proyectos' mike . notificar_observadores =comenzar El resultado de "¡Cortar un nuevo cheque para Mike!" "¡Su salario ahora es de 35000!" "¡Envía a Mike una nueva factura de impuestos!" =fin

Óxido

Código fuente en Rust /// El ejemplo describe cómo recibir datos de una estación meteorológica (estructura WeatherData, despachador de eventos) y /// utilizarlos para mostrarlos en la pantalla (estructura CurrentConditionsDisplay, detector de eventos). /// El oyente se registra con el observador usando el método register_observer, que toma un cierre y /// lo agrega a la lista de observadores. Cuando los datos meteorológicos cambian, se llama al método notificar_observadores, que cierra /// todos los oyentes y les pasa los datos actualizados. usar std :: rc :: Rc ; usar std :: celda :: RefCell ; tipo ObserverFn = Caja < dyn Fn ( f32 , f32 , i32 ) > ; rasgo Observable { fn register_observer ( & mut self , o : ObserverFn ) -> usize ; fn remove_observer ( & mut self , idx : usize ); fn notificar_observadores ( & mut self ); } #[derivar (predeterminado)] estructura WeatherData { observadores : Vec < ObserverFn > , temperatura : f32 , humedad : f32 , presión : i32 , } datos meteorológicos impl { fn set_measurements ( & mut self , temperatura : f32 , humedad : f32 , presión : i32 ) { uno mismo temperatura = temperatura ; uno mismo humedad = humedad ; uno mismo presión = presión ; uno mismo notificar_observadores (); } } impl Observable para WeatherData { fn register_observer ( & mut self , o : ObserverFn ) -> usar { uno mismo observadores _ empujar ( o ); uno mismo observadores _ Len () - 1 } fn remove_observer ( & mut self , idx : usesize ) { uno mismo observadores _ eliminar ( idx ); } fn notificar_observadores ( & mut self ) { para el observador en sí mismo . observadores _ iter () { ( * observador ) ( temperatura propia , humedad propia , presión propia ) ; _ } } } #[derivar (predeterminado)] estructura CurrentConditionsDisplay { temperatura : f32 , humedad : f32 , presión : i32 , } impl Visualización de las condiciones actuales { pantalla fn ( y yo ) { imprimir! ( "Ahora los valores son: {:.1} grados Celsius y {:.1} % de humedad. Presión {} mmHg." , uno mismo temperatura , auto . humedad , auto . presión ); } actualización fn ( & mut self , temperatura : f32 , humedad : f32 , presión : i32 ) { uno mismo temperatura = temperatura ; uno mismo humedad = humedad ; uno mismo presión = presión ; uno mismo mostrar (); } } fn principal () { let mut weather_data = WeatherData :: default (); let current_display = Rc :: new ( RefCell :: new ( CurrentConditionsDisplay :: default ())); let observador = pantalla_actual . clonar (); datos_del_tiempo . register_observer ( Box :: new ( mover | t , h , p | observador . presta_mut (). actualizar ( t , h , p ))); datos_del_tiempo . establecer_medidas ( 29.0 , 65.0 , 745 ); datos_del_tiempo . establecer_medidas ( 39.0 , 70.0 , 760 ); datos_del_tiempo . establecer_medidas ( 42.0 , 72.0 , 763 ); }

yo

código fuente de io # Un ejemplo es completamente idéntico al anterior en Python Observador := Objeto clon Observable := List clone do ( registrar := getSlot ( "push" ) notificar := método ( mensaje , self foreach ( observador , observador actualizar ( mensaje ))) ) Periódico := Observable clonar hacer ( addNews := método ( noticias , notificar ( noticias ))) Citizen := Observer clone do ( create := method ( name , self clone lexicalDo ( name := name )) update := method ( message , writeln ( name .. " found out: " .. message )) ) periodico := Clon de periodico diario hacer ( registrarse ( Ciudadano crear ( "Ivan" ) )) registrarse ( Ciudadano crear ( "Vasily" )) agregarNoticias ( "Observador - Patrón de diseño de comportamiento" ) ) #>>>> Ivan aprendió lo siguiente: The Observer es un patrón de diseño de comportamiento #>>>> Vasily aprendió lo siguiente: The Observer es un patrón de diseño de comportamiento

JavaScript ES6

Texto fuente en javascript clase Observable { constructor () { esto . oyentes = {}; } // Suscríbete. on ( e , callback ) { if ( this . oyentes [ e ] == indefinido ) { this . oyentes [ e ] = {}; esto _ oyentes [ e ] propiedad del evento = {}; esto _ oyentes [ e ] propiedad del evento . isOnOnce = falso ; esto _ oyentes [ e ] datos = []; } esto . oyentes [ e ] datos _ empujar ( devolución de llamada ); } // Suscríbete una vez. onOnce ( e , devolución de llamada ) { esto . en ( e , devolución de llamada ); esto _ oyentes [ e ] propiedad del evento . isOnOnce = verdadero ; } // Darse de baja. off ( e , devolución de llamada ) { this . oyentes [ e ] datos = esto . oyentes [ e ] datos _ filter ( function ( listener ) { return listener !== callback ; }); } // Enviar mensaje a los suscriptores. emit ( e , data ) { if ( this . listeners [ e ] == indefinido || this . listeners [ e ]. data == indefinido ) { return ; } let itObj = esto ; esto _ oyentes [ e ] datos _ forEach ( listener => { if ( itObj . listeners [ e ]. eventProperty . isOnOnce ) { itObj . off ( e , itObj . listeners [ e ]. data [ 0 ]); } listener ( data ); }); } }

Información adicional

En .NET Framework 4.0 , el patrón de diseño del observador se implementa implementando interfaces genéricas System.IObservable<T>y System.IObserver<T>[2] .

Literatura

  • Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides . Técnicas de diseño orientado a objetos. Patrones de diseño = Patrones de diseño. Elementos del Software Orientado a Objetos Reutilizables. - San Petersburgo. : Pedro, 2009. - 366 p. - ISBN 978-5-469-01136-1 .
  • Eric Freeman, Elizabeth Freeman. Patrones de diseño = Patrones de diseño Head First. - San Petersburgo. : Pedro, 2011. - 656 p. - ISBN 978-5-459-00435-9 .

Notas

  1. Patrón de observador . Consultado el 13 de junio de 2013. Archivado desde el original el 13 de junio de 2013.
  2. 1 2 Patrón de diseño del observador . Consultado el 13 de junio de 2013. Archivado desde el original el 13 de junio de 2013.
  3. Patrón de observador . Consultado el 4 de noviembre de 2019. Archivado desde el original el 4 de noviembre de 2019.