2009-12-22 13 views
14

Estoy lidiando con algunas situaciones de comunicación asíncrona (análisis XML basado en eventos, procesamiento de respuesta NSURLConnection, etc.). Trataré de explicar brevemente mi problema:Comunicación asincrónica Objective-c: patrón de objetivo/acción o delegación?

En mi situación actual, hay un proveedor de servicios (que puede hablar con un analizador xml o hacer algunas comunicaciones de red) y un cliente que puede solicitar al proveedor de servicios que realice de sus tareas asincrónicamente En este escenario, cuando el proveedor de servicios finaliza su procesamiento, debe comunicar los resultados al cliente.

Estoy tratando de encontrar un tipo de patrón o regla de oro para poner en práctica este tipo de cosas y veo 3 soluciones posibles:

1. Utilice el patrón delegación: el cliente es el proveedor de servicios de delegar y recibirá los resultados al completar la tarea.

2. Utilice un enfoque de objetivo/acción: El cliente le pide al proveedor de servicios que realice una tarea y pase un selector que deberá ser invocado por el proveedor de servicios una vez que haya finalizado la tarea.

3. Use las notificaciones.

( actualización) Después de un tiempo de tratar la solución # 2 (objetivo y acciones), que llegó a la conclusión de que, en mi caso, es mejor usar el enfoque de delegación (# 1). Aquí están los pros y los contras de cada opción, tal como los veo: enfoque

Delegación:

  • 1 (+) La ventaja de la opción 1 es que podemos cheque de compilación -time errors porque el cliente debe implementar el protocolo delegado del proveedor de servicios.

  • 1 (-) Esto también es un inconveniente porque hace que el cliente se acople estrechamente con el proveedor de servicios ya que tiene que implementar su protocolo de delegado.

  • 1 (+) Permite al programador navegar fácilmente por el código y encontrar qué método del cliente, el proveedor del servicio está invocando para pasar sus resultados.

  • 1 (-) Desde el punto de vista del cliente, no es tan fácil encontrar qué método será invocado por el proveedor del servicio una vez que tenga los resultados. Todavía es fácil, solo diríjase a los métodos de protocolo de delegados y eso es todo, pero el enfoque n. ° 2 es más directo.

  • 1 (-) Tenemos que escribir más código: defina el protocolo de delegado e impleméntelo.

  • 1 (-) Además, el patrón de delegación se debe utilizar, de hecho, para delegar el comportamiento. Este escenario no sería un caso exacto de delegación, semánticamente hablando.

Acción/Approach Target

  • 2 (+) La ventaja de la opción 2 es que cuando se está llamando el método de proveedor de servicios, el @selector especificando la acción devolución de llamada debe también se especificará, por lo que el programador sabe exactamente qué método se invocará de nuevo para procesar los resultados.

  • 2 (-) En oposición a esto, es difícil encontrar qué método volverá a llamarse en el cliente mientras navega por el código del proveedor de servicios. El programador debe ir a la invocación del servicio y ver qué @selector se está transfiriendo.

  • 2 (+) Es una solución más dinámica y causa menos acoplamiento entre las piezas.

  • 2 (-) Tal vez una de las cosas más importantes: Puede causar errores en tiempo de ejecución y los efectos secundarios, ya que el cliente puede pasar a un selector que no existe para el proveedor de servicios.

  • 2 (-) Utilizando el enfoque simple y estándar (#performSelector: withArgument: withArgument :) el proveedor de servicio sólo puede pasar hasta 2 argumentos.

Notificaciones:

  • no elegiría notificaciones porque creo que se supone que se utilizará cuando más de un objeto necesitan ser actualizados. Además, en esta situación, me gustaría decirle directamente al delegado/objeto de destino qué hacer después de generar los resultados.

Conclusión: En este punto, elegiría el mecanismo de delegación. Este enfoque proporciona más seguridad y permite navegar fácilmente por el código para seguir las consecuencias de enviar al delegado los resultados de las acciones del proveedor del servicio. Los aspectos negativos de esta solución son que: es una solución más estática, necesitamos escribir más código (relacionado con el protocolo) y, semánticamente hablando, no estamos hablando realmente de delegación porque el proveedor de servicios no estaría delegando nada .

¿Echo de menos algo? ¿Qué recomiendas y por qué?

Gracias!

Respuesta

0

Muy buena pregunta.

No creo que esté calificado, por el momento (como soy un novato), para comentar sobre qué patrón de diseño es mejor que el otro. Pero sólo quería mencionar que el lado negativo que ha mencionado en el punto 2 (a excepción de tiempo de ejecución) se puede evitar

if([delegate respondsToSelector:callback]){ 
    //call to callback here 
} 

Espero que ayude a sopesar las opciones

+0

Gracias Mihirsm, Tiene razón, eso evitará un error en tiempo de ejecución. Pero aún así, el hecho de que el programador usara un selector incorrecto no será visible hasta el tiempo de ejecución. Eso podría crear efectos secundarios: S. Nuevamente, una ventaja para el mecanismo de delegación más estático pero seguro. ¡Salud! – Lio

+1

Puede hacer que esto sea un poco más seguro implementando @protocol y haciendo que el delegado cumpla con este protocolo. Esto asegurará que la clase de delegado implemente los métodos requeridos. También puede agregar una aserción en su método setDelegate: para probar que el nuevo objeto se ajusta al protocolo. –

+0

La forma predeterminada para los métodos declarados en protocolos es que sean '@ optional', por lo que' [delegate respondsToSelector: callback] 'sigue siendo necesario. Puedes usar '@ required' en tu protocolo, pero he descubierto que la mayoría de las personas no lo hacen. Mi solución fue crear un trampolín 'NSProxy' devuelto por una extensión' NSObject', '- [NSObject ifResponds]'. Solo azúcar sintáctico que te permite no tener todas esas tonterías 'si'. –

3

Usted no olvida una tercera opción - notificaciones.

Puede hacer que el cliente observe una notificación del proveedor de servicios que indique que tiene nuevos datos disponibles. Cuando el cliente recibe esta notificación, puede consumir los datos del proveedor del servicio.

Esto permite un buen acoplamiento flojo; parte de la decisión depende solo de si desea un sistema push/pull.

+0

Gracias Ciarán, No pesé las notificaciones solo porque creo que deberían usarse cuando más de un objeto necesita ser notificado. Además, creo que en este tipo de situaciones, es mejor poder hablar directamente con el cliente (desde el punto de vista del proveedor de servicios) para informarle que la operación ha finalizado. Pero claro, Notificaciones es otra forma de manejar esto. Tal vez actualice la pregunta más tarde, incluidas las notificaciones, pero por ahora quiero ver qué sucede ... : D ¡Gracias de nuevo! – Lio

0

Otro inconveniente para el enfoque de delegación: Un proveedor de servicios solo puede tener un delegado. Si su proveedor de servicios es un singleton y tiene varios clientes, este patrón no funciona.

Esto me llevó a adoptar el enfoque de Acción/Objetivo. Mi proveedor de servicios tiene estado y se comparte entre varios clientes.

Cuestiones relacionadas