2009-08-19 13 views
26

Supongamos que tengo una clase Monkey que a veces necesita adquirir una instancia de Banana. La forma en que se proporciona este plátano no es de interés para el mono, pero sí inicia la adquisición del plátano.Evento, delegado o interfaz?

Ahora tengo al menos tres formas posibles de conectar mi mono a un proveedor de banano. ¿Cuál es la mejor manera de hacerlo?

1. Evento

criar a un evento Monkey.BananaNeeded. El controlador de eventos establece la propiedad BananaNeededEventArgs.Banana.

2. Interfaz

invocación IBananaProvider.GetBanana. La instancia IBananaProvider se inyecta en el mono como un argumento constructor o a través de una propiedad.

3. Delegado

invocar un delegado de tipo System.Func<Banana>. El delegado se inyecta en el mono como un argumento constructor o a través de una propiedad. Este es tentador porque no requiere la declaración de interfaces o clases adicionales, pero aparentemente no es una opción popular.

+3

+1 por divertidos ejemplos y una pregunta decente, pero por supuesto al mono no le importa si adquiere un plátano, lo único que le importa es comer un sabroso manjar. –

+2

Mono gordo: while (true) _provider.GetBanana.Eat(); – Guffa

+6

No olvide desechar las pieles de plátano. No queremos una fuga de piel de plátano en nuestras manos. –

Respuesta

6

No me gustan las opciones de evento y delegado a menos que haya un mecanismo para asegurar que no se adjuntarán varios controladores. La opción 2 es, por lo tanto, el ganador, IMO.

+0

No puede adjuntar más de un método a un delegado ... – Guffa

+4

@Guffa - ¿Eh? Todos los delegados en .NET son MulticastDelegate, y el punto es que usted * puede * asociarle varios métodos. ¿Cómo crees que funcionan los eventos? –

+0

Sí, puede combinar los delegados, pero es totalmente inútil en este caso, ya que solo el último puede devolver el plátano. – Guffa

1

La mejor manera en el escenario anterior es ir a la interfaz. En términos OOAD podemos definir el escenario anterior ya que la clase Monkey tiene una Banana.

1

que suelen utilizar el 2.

IBananaProvider bananaProvider = ProviderFactory.Get<IBananaProvider>(); 
+0

+1 ... pero ¿el mono no necesita saber cómo llegar a la fábrica para recoger su plátano? –

+0

@Justin Niessner: seguro, puede tener una fábrica de Providerfactory basada en un archivo de configuración. – Gregoire

4

El modelo de eventos funciona mejor si hay varios proveedores de plátanos posibles, es decir, el mono pide a todos los proveedores a su vez de un plátano, y el primero que puede proporcionar una consigue entregarlo.

Los otros dos modelos funcionan bien para un solo probador de plátano por mono. El delegado es más fácil de crear un proveedor, y la interfaz es más estructurada.

1

Existen operaciones en Monkey que hacen que necesite el Banana.

La necesidad de que el Mono obtenga una Banana se dedica a estas operaciones. Seguramente puede pasar el Plátano como parámetro para las operaciones.

Eliminaré la dependencia del dinero en un IBananaProvider.

class Monkey 
{ 
    void FeedWith(Banana banana) { ... } 
} 

Será la responsabilidad de quien llama obtener el plátano, no el mono.

Estoy defendiendo aquí no para inyectar servicios en las entidades.

+1

El mono podría necesitar un nuevo plátano cuando termine el primero. :-) – djna

+0

En este caso, pase el IBananaProvider como argumento, el mono puede decidir cuántos plátanos quiere. – thinkbeforecoding

+0

Pero, una vez más, Martin Fowler considera que el Anemic Monkey Model es un antipatrón: http://martinfowler.com/bliki/AnemicDomainModel.html –

1

Idealmente, la inyección de dependencia es el enfoque más generalmente aceptado.

Otro enfoque para probar es colas de mensajes.

En este escenario, Monkey podría esencialmente "publicar" un mensaje en alguna cola para obtener un delicioso plátano. Esta "publicación" desencadenaría algún proveedor de que está supervisando la cola, para luego cumplir con la solicitud, que la instancia real del proveedor responde es irrelevante. Monkey esperaría una respuesta al mensaje original y tomaría medidas cuando el paquete de interés llegue desde el BananaProvider.

Las colas de mensajes desacoplan proveedores y consumidores. Por supuesto, todavía hay alguna forma de contrato" en su lugar, pero que está en el otro extremo de la solicitud y la respuesta es irrelevante.

1

yo estaría de acuerdo y decir que la opción 2 es la mejor solución. Los delegados son Por lo general, está destinado a, bien delegar algo, en otras palabras, hacer algo, y los eventos están destinados a la respuesta inmediata a algo que sucedió, generalmente relacionado con el usuario. La interfaz simplemente dice: "Esto está aquí y puedes hacerlo". No quiere que el plátano o el mono hagan nada al principio y no quiere que el usuario interactúe directamente con el funcionamiento interno de su código, una interfaz lo gana. Todo lo que necesita es saber que el mono puede recibir plátanos. Lo que él decida hacer con esos plátanos después depende de él, y el plátano en sí, así como el código que lo rodea, no deberían preocuparse por eso.

Cuestiones relacionadas