fbpx
Wikipedia

Observer (patrón de diseño)

Observador (en inglés: Observer) es un patrón de diseño de software que define una dependencia del tipo uno a muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, notifica este cambio a todos los dependientes. Se trata de un patrón de comportamiento (existen de tres tipos: creación, estructurales y de comportamiento), por lo que está relacionado con algoritmos de funcionamiento y asignación de responsabilidades a clases y objetos.

Los patrones de comportamiento describen no solamente estructuras de relación entre objetos o clases sino también esquemas de comunicación entre ellos y se pueden clasificar en función de que trabajen con clases (método plantilla) u objetos (cadena de responsabilidad, comando, iterador, recuerdo, observador, estado, estrategia, visitante).

La variación de la encapsulación es la base de muchos patrones de comportamiento, por lo que cuando un aspecto de un programa cambia frecuentemente, estos patrones definen un objeto que encapsula dicho aspecto. Los patrones definen una clase abstracta que describe la encapsulación del objeto.

Este patrón también se conoce como el patrón de publicación-inscripción o modelo-patrón. Estos nombres sugieren las ideas básicas del patrón, que son: el objeto de datos, que se le puede llamar Sujeto a partir de ahora, contiene atributos mediante los cuales cualquier objeto observador o vista se puede suscribir a él pasándole una referencia a sí mismo. El Sujeto mantiene así una lista de las referencias a sus observadores. Los observadores a su vez están obligados a implementar unos métodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores suscritos los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto, ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno. Este patrón suele utilizarse en los entornos de trabajo de interfaces gráficas orientados a objetos, en los que la forma de capturar los eventos es suscribir listeners a los objetos que pueden disparar eventos.

El patrón observador es la clave del patrón de arquitectura Modelo Vista Controlador (MVC).[1]​ De hecho el patrón fue implementado por primera vez en el MVC de Smalltalk basado en un entorno de trabajo de interfaz.[2]​ Este patrón está implementado en numerosos bibliotecas y sistemas, incluyendo todos los toolkits de GUI.

Patrones relacionados: publicador-subscriptor, mediador, singleton.

Objetivo

Definir una dependencia uno a muchos entre objetos, de tal forma que cuando el objeto cambie de estado, todos sus objetos dependientes sean notificados automáticamente. Se trata de desacoplar la clase de los objetos clientes del objeto, aumentando la modularidad del lenguaje, creando las mínimas dependencias y evitando bucles de actualización (espera activa o sondeo). En definitiva, normalmente, se usará el patrón observador cuando un elemento quiere estar pendiente de otro, sin tener que estar comprobando de forma continua si ha cambiado o no.

Motivación

Si se necesita consistencia entre clases relacionadas, pero con independencia, es decir, con un bajo acoplamiento.

Ámbito de aplicación

Puede pensarse en aplicar este patrón cuando una modificación en el estado de un objeto requiere cambios de otros, y no se desea que se conozca el número de objetos que deben ser cambiados. También cuando se quiere que un objeto sea capaz de notificar a otros objetos sin hacer ninguna suposición acerca de los objetos notificados y cuando una abstracción tiene dos aspectos diferentes, que dependen uno del otro; si se encapsulan estos aspectos en objetos separados se permitirá su variación y reutilización de modo independiente.

Estructura

 

Participantes

Habrá sujetos concretos cuyos cambios pueden resultar interesantes a otros y observadores a los que al menos les interesa estar pendientes de un elemento y en un momento dado, reaccionar ante sus notificaciones de cambio. Todos los sujetos tienen en común que un conjunto de objetos quieren estar pendientes de ellos. Cualquier elemento que quiera ser observado tiene que permitir indicar:

  1. “Estoy interesado en tus cambios”.
  2. “Ya no estoy interesado en tus cambios”.

El observable tiene que tener, además, un mecanismo de aviso a los interesados.

A continuación se detallan a los participantes de forma desglosada:

  • Sujeto (subject):
El sujeto proporciona una interfaz para agregar (attach) y eliminar (detach) observadores. El Sujeto conoce a todos sus observadores.
  • Observador (observer):
Define el método que usa el sujeto para notificar cambios en su estado (update/notify).
  • Sujeto concreto (concrete subject):
Mantiene el estado de interés para los observadores concretos y los notifica cuando cambia su estado. No tienen porque ser elementos de la misma jerarquía.
  • Observador concreto (concrete observer):
Mantiene una referencia al sujeto concreto e implementa la interfaz de actualización, es decir, guardan la referencia del objeto que observan, así en caso de ser notificados de algún cambio, pueden preguntar sobre este cambio.

Colaboraciones

La colaboración más importante en este patrón es entre el sujeto y sus observadores, ya que en el momento en el que el sujeto sufre un cambio, este notifica a sus observadores.

 
Diagrama de secuencia

Consecuencias

Las consecuencias de aplicar este patrón pueden ser tanto beneficiosas como pueden perjudicar algunos aspectos. Por una parte abstrae el acoplamiento entre el sujeto y el observador, lo cual es beneficioso ya que se consigue una mayor independencia y además el sujeto no necesita especificar los observadores afectados por un cambio. Por otro lado, con el uso de este patrón ocurre que se van a desconocer las consecuencias de una actualización, lo cual, dependiendo del problema, puede afectar en mayor o menor medida (por ejemplo, al rendimiento).

Implementación

A continuación se detallan una serie de problemas que se pueden presentar a la hora de implementar este patrón:

  • Problema 1:
Para evitar que el observador concreto tenga una asociación con el sujeto concreto, se podría hacer que la relación entre sujeto y observador fuese bidireccional, evitando así asociaciones concretas, el problema es que dejaría de ser una interfaz. El que deje de ser una interfaz puede producir problemas si el lenguaje de programación no soporta la herencia múltiple.
Se podría eliminar la bidireccionalidad de la asociación pasando el sujeto como parámetro al método actualizar y ya no se tendría que referenciar el objeto observado. Esto podría causar problemas si se observan varios objetos, tanto de la misma clase como de distintas, ya que no elimina dependencias, y para hacer operaciones específicas sobre el objeto actualizado obliga a hacer en la implementación.
  • Problema 2:
Si hay muchos sujetos sin observador, la estructura de los observadores está desaprovechada, para solucionarlo se puede tener un intermediario que centralice el almacenamiento de la asociación de cada sujeto con sus observadores. Para esta solución se crea ese gestor de observadores usando el patrón singleton (instancia única), ya que proporciona una única referencia y no una por cada sujeto. El gestor aunque mejora el aprovechamiento del espacio, hace que se reduzca el rendimiento y se pierde eficiencia en el método notificar.
  • Problema 3:
El responsable de iniciar la comunicación es el sujeto concreto, pero se puede dar un problema cuando el objeto concreto está siendo actualizado de forma continua ya que debido a esto se tendría que realizar muchas actualizaciones en muy poco tiempo. La solución sería suspender temporalmente las llamadas al método de actualización/notificación; por ejemplo, haciendo que el cliente pueda activar o desactivar las notificaciones y notificar todos los cambios cuando las vuelva a habilitar. El patrón Estado sería una posible solución para diseñar esta variante de no notificar si no se han dado cambios o hacerlo en caso de que si.
  • Problema 4 (referencias inválidas):
A la hora de implementar este patrón se debe tener cuidado cuando un elemento observable desaparece. En ciertos lenguajes será el gestor de memoria el que cada cierto tiempo debe de limpiar las referencias liberadas, pero si un observable que sigue siendo observado puede no liberarse nunca. Para solucionar este problema puede crearse una función destruir que notifique al gestor que el elemento observable va a desaparecer y si no se está usando la variante del gestor el observable directamente desregistrará a sus observadores. Antes de esto hay que eliminar las referencias a este elemento, por tanto, hay que eliminar a los observadores antes de eliminar al observable, ya que así se evitará tanto que aparezcan referencias inválidas al objeto una vez este haya sido eliminado, como que se produzcan operaciones inválidas intentando invocarlo.
Se puede avisar a los observadores creando un método actualizar especial, en el que se tendrían dos opciones:
  1. El observador también muere.
  2. El observador sigue vivo, pero apunta a nulo.
  • Problema 5:
Ya que se debe asegurar la consistencia del estado del sujeto antes de iniciar una notificación, siempre se notificará al final, ya que aunque en entorno multihilo se notifica antes de hacer los cambios, puede que los observadores soliciten información al observable cuando aún se van a hacer más cambios y se darían problemas de consistencia si se accede a un estado que aún no es el definitivo. De esta forma, los observadores ya no accederán a sujetos en estado inconsistente.

Por ejemplo:

Secuencia incorrecta: a b c notificar() d e f Secuencia correcta: a b c d e f notificar() 

Jerarquía con varios tipos des observadores: en este caso el hilo redefine cambios, no los notifica.

 
Jerarquía de varios observadores
  • Problema 6:
En mecanismos de notificación tradicionalmente hay dos opciones: pull que es la que propone el patrón observador; y push que es la que se tendría si se incluye información como parámetros en el mecanismo de actualización. El problema de hacer esto es que la interfaz del observador se vuelve más específica y por tanto menos genérica y reutilizable.

PULL: los objetos avisan de que han cambiado y el observador pregunta cuál ha sido el cambio.

PUSH: minimiza (eficiencia) que cuando algo cambia y se informará a todos los interesados, se realicen el menor número de llamadas posibles.

Dependiendo del problema que haya que resolver, se habrá de valorar que implementación se ajusta mejor para resolverlo de la forma más eficiente y efectiva o si las variantes anteriores pueden combinarse entre sí dependiendo de las características de escenario concreto. Por ejemplo, la opción 2 podría aplicarse cuando interese aplicar en un sujeto concreto n métodos seguidos y no se quiere notificar hasta que todos finalicen su ejecución.

Java

Soporte Java para el patrón Observador:

 Clase java.util.Observable addObserver(o Observer) deleteObserver(o Observer) notifyObserver() notifyObservers(Object data) 
 Interface java.util.Observer void update (Observable o, Object data) 

Ejemplos

Los siguientes ejemplos muestran un programa que lee del teclado, y cada línea se tratara como un evento. Cuando una línea es obtenida, se llama al método que notificara a los observadores, tal que todos los observadores fueran avisados de la ocurrencia del evento mediante sus métodos de actualización.

Ejemplo 1 en Java

En el caso de Java, el método de actualización seria notifyObservers.

import java.util.Scanner; import java.util.Observable; public class FuenteEvento extends Observable implements Runnable { public void run() { while (true) { String respuesta = new Scanner(System.in).next(); setChanged(); notifyObservers(respuesta); } } } 
import java.util.Observable; public class MiApp { public static void main(String[] args) { System.out.println("Introducir Texto: "); FuenteEvento fuenteEvento = new FuenteEvento(); fuenteEvento.addObserver(new Observer(){ @Override public void update(Observable obj, Object arg){ System.out.println("\nRespuesta recibida: " + arg); } }); new Thread(fuenteEvento).start(); } } 

Ejemplo 2 en Python

En el lenguaje Python, el método de actualización seria notify. Un ejemplo más sencillo, pero parecido al anterior sería el siguiente:

class Listener: def __init__(self, name, subject): self.name = name subject.register(self) def notify(self, event): print self.name, "received event", event 
class Subject: def __init__(self): self.listeners = [] def register(self, listener): self.listeners.append(listener) def unregister(self, listener): self.listeners.remove(listener) def notify_listeners(self, event): for listener in self.listeners: listener.notify(event) 
subject = Subject() listenerA = Listener("<listener A>", subject) listenerB = Listener("<listener B>", subject) # El objeto Subject ahora tiene dos "escuchadores" registrados subject.notify_listeners ("<event 1>") # La salida obtenida es : # <listener A> received event <event 1> # <listener B> received event <event 1> 


Diagramas correspondientes al ejemplo 1

 
Diagrama de clases
 
Diagrama de objetos

Enlaces externos

  •   Wikilibros alberga un libro o manual sobre Patrones de Comportamiento.

Referencias

  1. «Model-View-Controller». MSDN. Consultado el 1 de junio de 2013. 
  2. Gang Of Four
  •   Datos: Q818562
  •   Multimedia: Observer pattern

observer, patrón, diseño, este, artículo, sección, necesita, wikificado, favor, edítalo, para, cumpla, convenciones, estilo, este, aviso, puesto, marzo, 2014, observador, inglés, observer, patrón, diseño, software, define, dependencia, tipo, muchos, entre, obj. Este articulo o seccion necesita ser wikificado por favor editalo para que cumpla con las convenciones de estilo Este aviso fue puesto el 30 de marzo de 2014 Observador en ingles Observer es un patron de diseno de software que define una dependencia del tipo uno a muchos entre objetos de manera que cuando uno de los objetos cambia su estado notifica este cambio a todos los dependientes Se trata de un patron de comportamiento existen de tres tipos creacion estructurales y de comportamiento por lo que esta relacionado con algoritmos de funcionamiento y asignacion de responsabilidades a clases y objetos Los patrones de comportamiento describen no solamente estructuras de relacion entre objetos o clases sino tambien esquemas de comunicacion entre ellos y se pueden clasificar en funcion de que trabajen con clases metodo plantilla u objetos cadena de responsabilidad comando iterador recuerdo observador estado estrategia visitante La variacion de la encapsulacion es la base de muchos patrones de comportamiento por lo que cuando un aspecto de un programa cambia frecuentemente estos patrones definen un objeto que encapsula dicho aspecto Los patrones definen una clase abstracta que describe la encapsulacion del objeto Este patron tambien se conoce como el patron de publicacion inscripcion o modelo patron Estos nombres sugieren las ideas basicas del patron que son el objeto de datos que se le puede llamar Sujeto a partir de ahora contiene atributos mediante los cuales cualquier objeto observador o vista se puede suscribir a el pasandole una referencia a si mismo El Sujeto mantiene asi una lista de las referencias a sus observadores Los observadores a su vez estan obligados a implementar unos metodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores suscritos los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado De manera que cuando se produce un cambio en el Sujeto ejecutado por ejemplo por alguno de los observadores el objeto de datos puede recorrer la lista de observadores avisando a cada uno Este patron suele utilizarse en los entornos de trabajo de interfaces graficas orientados a objetos en los que la forma de capturar los eventos es suscribir listeners a los objetos que pueden disparar eventos El patron observador es la clave del patron de arquitectura Modelo Vista Controlador MVC 1 De hecho el patron fue implementado por primera vez en el MVC de Smalltalk basado en un entorno de trabajo de interfaz 2 Este patron esta implementado en numerosos bibliotecas y sistemas incluyendo todos los toolkits de GUI Patrones relacionados publicador subscriptor mediador singleton Indice 1 Objetivo 2 Motivacion 3 Ambito de aplicacion 4 Estructura 5 Participantes 6 Colaboraciones 7 Consecuencias 8 Implementacion 9 Java 10 Ejemplos 10 1 Ejemplo 1 en Java 10 2 Ejemplo 2 en Python 11 Diagramas correspondientes al ejemplo 1 12 Enlaces externos 13 ReferenciasObjetivo EditarDefinir una dependencia uno a muchos entre objetos de tal forma que cuando el objeto cambie de estado todos sus objetos dependientes sean notificados automaticamente Se trata de desacoplar la clase de los objetos clientes del objeto aumentando la modularidad del lenguaje creando las minimas dependencias y evitando bucles de actualizacion espera activa o sondeo En definitiva normalmente se usara el patron observador cuando un elemento quiere estar pendiente de otro sin tener que estar comprobando de forma continua si ha cambiado o no Motivacion EditarSi se necesita consistencia entre clases relacionadas pero con independencia es decir con un bajo acoplamiento Ambito de aplicacion EditarPuede pensarse en aplicar este patron cuando una modificacion en el estado de un objeto requiere cambios de otros y no se desea que se conozca el numero de objetos que deben ser cambiados Tambien cuando se quiere que un objeto sea capaz de notificar a otros objetos sin hacer ninguna suposicion acerca de los objetos notificados y cuando una abstraccion tiene dos aspectos diferentes que dependen uno del otro si se encapsulan estos aspectos en objetos separados se permitira su variacion y reutilizacion de modo independiente Estructura Editar Participantes EditarHabra sujetos concretos cuyos cambios pueden resultar interesantes a otros y observadores a los que al menos les interesa estar pendientes de un elemento y en un momento dado reaccionar ante sus notificaciones de cambio Todos los sujetos tienen en comun que un conjunto de objetos quieren estar pendientes de ellos Cualquier elemento que quiera ser observado tiene que permitir indicar Estoy interesado en tus cambios Ya no estoy interesado en tus cambios El observable tiene que tener ademas un mecanismo de aviso a los interesados A continuacion se detallan a los participantes de forma desglosada Sujeto subject El sujeto proporciona una interfaz para agregar attach y eliminar detach observadores El Sujeto conoce a todos sus observadores Observador observer Define el metodo que usa el sujeto para notificar cambios en su estado update notify Sujeto concreto concrete subject Mantiene el estado de interes para los observadores concretos y los notifica cuando cambia su estado No tienen porque ser elementos de la misma jerarquia Observador concreto concrete observer Mantiene una referencia al sujeto concreto e implementa la interfaz de actualizacion es decir guardan la referencia del objeto que observan asi en caso de ser notificados de algun cambio pueden preguntar sobre este cambio Colaboraciones EditarLa colaboracion mas importante en este patron es entre el sujeto y sus observadores ya que en el momento en el que el sujeto sufre un cambio este notifica a sus observadores Diagrama de secuenciaConsecuencias EditarLas consecuencias de aplicar este patron pueden ser tanto beneficiosas como pueden perjudicar algunos aspectos Por una parte abstrae el acoplamiento entre el sujeto y el observador lo cual es beneficioso ya que se consigue una mayor independencia y ademas el sujeto no necesita especificar los observadores afectados por un cambio Por otro lado con el uso de este patron ocurre que se van a desconocer las consecuencias de una actualizacion lo cual dependiendo del problema puede afectar en mayor o menor medida por ejemplo al rendimiento Implementacion EditarA continuacion se detallan una serie de problemas que se pueden presentar a la hora de implementar este patron Problema 1 Para evitar que el observador concreto tenga una asociacion con el sujeto concreto se podria hacer que la relacion entre sujeto y observador fuese bidireccional evitando asi asociaciones concretas el problema es que dejaria de ser una interfaz El que deje de ser una interfaz puede producir problemas si el lenguaje de programacion no soporta la herencia multiple Se podria eliminar la bidireccionalidad de la asociacion pasando el sujeto como parametro al metodo actualizar y ya no se tendria que referenciar el objeto observado Esto podria causar problemas si se observan varios objetos tanto de la misma clase como de distintas ya que no elimina dependencias y para hacer operaciones especificas sobre el objeto actualizado obliga a hacer en la implementacion Problema 2 Si hay muchos sujetos sin observador la estructura de los observadores esta desaprovechada para solucionarlo se puede tener un intermediario que centralice el almacenamiento de la asociacion de cada sujeto con sus observadores Para esta solucion se crea ese gestor de observadores usando el patron singleton instancia unica ya que proporciona una unica referencia y no una por cada sujeto El gestor aunque mejora el aprovechamiento del espacio hace que se reduzca el rendimiento y se pierde eficiencia en el metodo notificar Problema 3 El responsable de iniciar la comunicacion es el sujeto concreto pero se puede dar un problema cuando el objeto concreto esta siendo actualizado de forma continua ya que debido a esto se tendria que realizar muchas actualizaciones en muy poco tiempo La solucion seria suspender temporalmente las llamadas al metodo de actualizacion notificacion por ejemplo haciendo que el cliente pueda activar o desactivar las notificaciones y notificar todos los cambios cuando las vuelva a habilitar El patron Estado seria una posible solucion para disenar esta variante de no notificar si no se han dado cambios o hacerlo en caso de que si Problema 4 referencias invalidas A la hora de implementar este patron se debe tener cuidado cuando un elemento observable desaparece En ciertos lenguajes sera el gestor de memoria el que cada cierto tiempo debe de limpiar las referencias liberadas pero si un observable que sigue siendo observado puede no liberarse nunca Para solucionar este problema puede crearse una funcion destruir que notifique al gestor que el elemento observable va a desaparecer y si no se esta usando la variante del gestor el observable directamente desregistrara a sus observadores Antes de esto hay que eliminar las referencias a este elemento por tanto hay que eliminar a los observadores antes de eliminar al observable ya que asi se evitara tanto que aparezcan referencias invalidas al objeto una vez este haya sido eliminado como que se produzcan operaciones invalidas intentando invocarlo Se puede avisar a los observadores creando un metodo actualizar especial en el que se tendrian dos opciones El observador tambien muere El observador sigue vivo pero apunta a nulo Problema 5 Ya que se debe asegurar la consistencia del estado del sujeto antes de iniciar una notificacion siempre se notificara al final ya que aunque en entorno multihilo se notifica antes de hacer los cambios puede que los observadores soliciten informacion al observable cuando aun se van a hacer mas cambios y se darian problemas de consistencia si se accede a un estado que aun no es el definitivo De esta forma los observadores ya no accederan a sujetos en estado inconsistente Por ejemplo Secuencia incorrecta a b c notificar d e f Secuencia correcta a b c d e f notificar Jerarquia con varios tipos des observadores en este caso el hilo redefine cambios no los notifica Jerarquia de varios observadores Problema 6 En mecanismos de notificacion tradicionalmente hay dos opciones pull que es la que propone el patron observador y push que es la que se tendria si se incluye informacion como parametros en el mecanismo de actualizacion El problema de hacer esto es que la interfaz del observador se vuelve mas especifica y por tanto menos generica y reutilizable PULL los objetos avisan de que han cambiado y el observador pregunta cual ha sido el cambio PUSH minimiza eficiencia que cuando algo cambia y se informara a todos los interesados se realicen el menor numero de llamadas posibles Dependiendo del problema que haya que resolver se habra de valorar que implementacion se ajusta mejor para resolverlo de la forma mas eficiente y efectiva o si las variantes anteriores pueden combinarse entre si dependiendo de las caracteristicas de escenario concreto Por ejemplo la opcion 2 podria aplicarse cuando interese aplicar en un sujeto concreto n metodos seguidos y no se quiere notificar hasta que todos finalicen su ejecucion Java EditarSoporte Java para el patron Observador Clase java util Observable addObserver o Observer deleteObserver o Observer notifyObserver notifyObservers Object data Interface java util Observer void update Observable o Object data Ejemplos EditarLos siguientes ejemplos muestran un programa que lee del teclado y cada linea se tratara como un evento Cuando una linea es obtenida se llama al metodo que notificara a los observadores tal que todos los observadores fueran avisados de la ocurrencia del evento mediante sus metodos de actualizacion Ejemplo 1 en Java Editar En el caso de Java el metodo de actualizacion seria notifyObservers import java util Scanner import java util Observable public class FuenteEvento extends Observable implements Runnable public void run while true String respuesta new Scanner System in next setChanged notifyObservers respuesta import java util Observable public class MiApp public static void main String args System out println Introducir Texto FuenteEvento fuenteEvento new FuenteEvento fuenteEvento addObserver new Observer Override public void update Observable obj Object arg System out println nRespuesta recibida arg new Thread fuenteEvento start Ejemplo 2 en Python Editar En el lenguaje Python el metodo de actualizacion seria notify Un ejemplo mas sencillo pero parecido al anterior seria el siguiente class Listener def init self name subject self name name subject register self def notify self event print self name received event event class Subject def init self self listeners def register self listener self listeners append listener def unregister self listener self listeners remove listener def notify listeners self event for listener in self listeners listener notify event subject Subject listenerA Listener lt listener A gt subject listenerB Listener lt listener B gt subject El objeto Subject ahora tiene dos escuchadores registrados subject notify listeners lt event 1 gt La salida obtenida es lt listener A gt received event lt event 1 gt lt listener B gt received event lt event 1 gt Diagramas correspondientes al ejemplo 1 Editar Diagrama de clases Diagrama de objetosEnlaces externos Editar Wikilibros alberga un libro o manual sobre Patrones de Comportamiento LazyLoading Patron ObserverReferencias Editar Model View Controller MSDN Consultado el 1 de junio de 2013 Gang Of Four Datos Q818562 Multimedia Observer pattern Obtenido de https es wikipedia org w index php title Observer patron de diseno amp oldid 138867555, wikipedia, wiki, leyendo, leer, libro, biblioteca,

español

, española, descargar, gratis, descargar gratis, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, imagen, música, canción, película, libro, juego, juegos