Patrón Interfaz Marcadora (I)
Segunda parte de esta entrada: Patrón Interfaz Marcadora (II)
Introducción
Uno de los patrones más desconocidos en general y no por ello infrautilizado, es el Patrón de Interfaz Marcadora o Marker Interface Pattern.
En .NET tenemos dos formas de implementar este patrón. En esta primera entrada sobre este patrón veremos una de estas formas.
¿Qué es el Patrón Interfaz Marcadora?
Lo primero de todo es entender bien qué es o en qué consiste el Patrón Interfaz Marcadora.
Se trata de un patrón de diseño que puede ser utilizado para proporcionar información marcadora sobre un objeto concreto.
El objetivo de este patrón es el de indicar el comportamiento de la clase que la implementa.
Sin embargo, debe quedar claro para evitar dudas, que una interfaz marcadora es aquella que carece de miembros, es decir, que sirve para marcar. Además de esto, al carecer de miembros, no define ningún contrato que pueda ser implementado.
Clases y subclases
Hablando de herencia, debemos tener claro un aspecto que seguramente dominaremos todos a estas alturas. Si tenemos una clase que implementa una interfaz marcadora y una subclase que hereda de esa clase, ésta también arrastrará consigo esa interfaz marcadora. Es algo obvio, pero debemos tenerlo en cuenta.
¿Cómo funciona?
Comprenderemos mejor el funcionamiento de este patrón con un ejemplo en código C#.
Para ello, crearemos inicialmente una interfaz vacía como por ejemplo:
1: public interface IMarcadoraFoo
2: {
3: } // IMarcadoraFoo
Luego, tendremos una clase que implementará esta interfaz marcadora, como por ejemplo la clase Foo:
1: public class Foo : IMarcadoraFoo
2: {
3: } // Foo
Si dispongo de un método o función que interactúe de alguna manera con una clase Foo, podré preguntarle si implementa esta interfaz marcadora.
Un ejemplo sencillo de como preguntar si una clase implementa la interfaz marcadora es hacerlo de la siguiente manera:
1: Foo foo = new Foo();
2: if (foo is IMarcadoraFoo)
3: {
4: MessageBox.Show("Es marcadora");
5: }
6: else
7: {
8: MessageBox.Show("No es marcadora");
9: }
Como podemos apreciar en el código anterior, hemos verificado que la clase Foo con la que queremos trabajar es una clase que implementa la interfaz marcadora IMarcadoraFoo.
No obstante, existe otra forma más recomendable en .NET de implementar al Patrón Interfaz Marcadora, y es hacerlo con atributos. Esto lo veremos en la próxima entrega.
Referencias
Marker Interface Pattern (Wikipedia)
Segunda parte de esta entrada: Patrón Interfaz Marcadora (II)
7 Responsesso far
Buenas Jorge! 😉
Usar interfaces para «marcar» comportamiento me parece algo a evitar siempre que sea posible. La razón es muy simple: Usar una interfaz para «marcar» una clase hace que la «marca» se propague a todas las subclases. Lo que no siempre es desable.
Sé que tienes pendiente la segunda entrega donde mostrarás el uso de atributos, pero queria dejarlo claro aquÃ. Si el lenguaje no soporta metadatos, el uso de una interfaz marcadora es casi obligatorio (lo que ocurrÃa en las versiones de Java anteriores a la 5). Pero en C# no creo que deba ser utilizada!
Saludos! 😉
Efectivamente Eduard, lo que comentas acerca de la propagación es lo que indicaba en el apartado de la entrada «Clases y subclases».
Como todo, tiene sus ventajas e inconvenientes, pero a veces es bueno conocerla por si nos interesa utilizarla.
Y sobre lo que comentas, efectivamente la segunda parte (que ya está escrita y saldrá mañana publicada) habla sobre atributos, que bajo mi punto de vista, me gusta más que las interfaces, y sÃ, has dado en el clavo cuando comentas que en el caso de no soportar metadatos es precisamente cuando debemos «jugar» con las interfaces marcadoras.
Tus comentarios muy precisos y correctos como siempre y complementa la entrada fantásticamente.
Muchas gracias por comentar. :)))
Estoy de acuerdo en que usar asà un interface no es lo más recomendable, pero me pregunto si a nivel de eficiencia compensa para poder usar el operador «is» en lugar de tener que tirar de reflection para sacar los atributos que le vais a poner a la pobre clase mañana.
Juanma.
@Juanma
Bueno. Puede haber algún caso ultra-crÃtico de rendimiento que compense esos ns de diferencia que pueda haber entre ambas opciones. Pero seguramente ya no usarás .NET en este caso. 😀
De hecho el uso de este patrón usando interfaces está explÃcitamente NO recomendado por Microsoft (http://msdn.microsoft.com/en-us/library/ms229022.aspx)
Dicho esto, hay casos en que pueda ser aplicable. Mark Seemaan muesta uno en su blog (http://blog.ploeh.dk/default,date,2011-12-19.aspx). Pero no es por rendimiento, es por imposibilidad de usar un atributo en este caso.
Yo considero el uso del marker interface como un code smell… Eso significa que «salta mi alarma interna» y miro con detalle el código en estos casos.
Y por último, no hay balas de plata en este mundo. Decir algo como «esto no deberÃa ser usado», deberÃa ser interpretado como «no deberÃa ser usado en la gran mayorÃa de casos». 😉
Un saludo! 😉
Es buen patrón en algunos casos. Yo lo he utilizado para algun programa.
Por ejemplo, en un repositorio he marcado que el tipo genérico debe ser de tipo IAggregateRoot, ya que en DDD los repositorios sólo son para los Aggregate Root.
De esta forma, marco mis AggregateRoot con esta interface haciendo más sólido el sistema, aunque más rÃgido.
Para el caso normal, efectivamente da igual la eficiencia.
Estaba pensando en casos más especÃficos, como el arranque de una aplicación que requiera mucho reflection, por ejempo para inicializar contenedores o cosas similares y no queramos penalizar el tiempo de arranque.
De todas formas, como en cualquier aspecto relacionado con la eficiencia si no se mide no tiene sentido especular.
Introducción En la entrada anterior , vimos en qué consistía el Patrón Interfaz