« Estructuras de datos: tabla hash | Inicio | Patrones de diseño: Modelo-vista-controlador ( de verdad ) »

Patrones de diseño: MVC (Modelo.vista-controlador)

Vamos a hacer un contador de tiempo inverso. Al hacer un click en el fondo se inicializa el contador, que se puede poner en pausa haciendo otro click en el fondo. Haciendo otro click más se vuelve a arrancar

Podeis encontrar una explicación muy completa de en qué consiste el patrón MVC aquí

Básicamente, se trata de dividir la aplicación en tres capas. El modelo, son los datos o la lógica de la aplicación, la vista el interfaz, y el controlador el encargado de unir uno y otro, es decir, de actualizar los datos cuando se manipula el interfaz, y de actualizar el interfaz cuando cambian los datos.

En nuestro caso, el modelo es una clase AS2 que es la encargada de llevar la cuenta del tiempo. A cada segundo, emite un evento, que recibe el controlador, que a su vez, se encargará de actualizar la vista, que es un campo de texto donde se presenta el tiempo restante. Cuando se hace un click en el fondo, la vista comunica el click al controlador, que a su vez, comunica al modelo que debe cambiar su estado (para si estaba arrancado, o arrancar si estaba parado).

Aprovechamos que el orden de carga ( configuración de publicación ) del swf es de abajo a arriba, para instanciar el controlador en la primera capa del primer frame , y la vista en la segunda capa del primer frame.

Para instanciar el controlador:

import net.designnation.patterns.* var myController: controller = new controller( this ); myController.init( 60 );

El controlador tiene agregado una instancia del modelo, de manera que en el modelo se instancia en el método init( ) del controlador :

public function init( time: Number ) { this.myClock = new clock( this.timeline, time ); this.myClock.addEventListener( "endOfTime", this ); this.myClock.addEventListener( "updateTime", this ); this.myClock.init( ); }

De este modo, se instancia la clase clock, pasándola como parámetros una referencia al _root, y el tiempo total. Esa referencia al _root se utiliza para crear un clip vacío, en cuyo onEnterFrame se decrementa el tiempo total.

public function init( ) { this.clockClip = timeline.createEmptyMovieClip( "empty", this.timeline.getNextHighestDepth( ) ); this.clockClip[ "owner" ] = this; this.clockClip.onEnterFrame = function ( ) { if ( this[ "owner" ].workingFlag ) { if ( this[ "owner" ].actualTime>= 1 ) { this[ "owner" ].actualTime--; if ( this[ "owner" ].actualTime % FRAMERATE == 0 ) { this[ "owner" ].dispatchTime( this[ "owner"].actualTime ); } } else { this[ "owner" ].dispatchTime( ); delete this.onEnterFrame; } } } }

Observemos la sintaxis de la línea

this.clockClip[ "owner" ] = this;

Es lo mismo que escribir

this.clockClip.owner = this;

El hecho de meter "owner" entre corchetes es tan sólo para identificar esa propiedad con un vistazo como una propiedad que he creado dinámicamente. Por tanto, es una de las convenciones que yo utilizo, no tiene mayor significado.

Como puede verse, cuando hace falta actualizar el campo de texto con el tiempo restante, la instancia de clock dispara un evento

private function dispatchTime( actualTime: Number ) { if ( actualTime == null ) { var event = "endOfTime"; } else { var event = "updateTime"; } this.dispatchEvent( {type: event, target: this, time: ( actualTime/ FRAMERATE ) } ); }

Como el controlador está registrado como listener de clock, se ejecuta el método correspondiente:

public function updateTime( arg: Object ) { this.timeline.clock.text = arg.time; }

que es el que se encarga de actualizar la vista.

En sentido contrario, la lógica es parecida, salvo que se ejecutan directamente los métodos públicos correspondientes ( que, en realidad deberían formar parte de un interfaz de comunicación, pero eso ya es complicarnos demasiado por hoy ).

Cuando se hace click en el fondo,

this.onMouseUp = function( ) { myController.changeClockState( "clock" ); }

Y en el controlador:

public function changeClockState( ) { this.myClock.changeClockState( ); }

Y finalmente, en la clase clock:

public function changeClockState( ) { this.workingFlag = !this.workingFlag; }

Resumiendo, todas las comunicaciones en uno u otro sentido se harán a través del controlador. De ese modo, aseguramos la independencia entre la parte gráfica de la aplicación y los datos de la misma, y por tanto nuestra aplicación será más modular, más fácil de mantener, de modificar, nuestro código estará más estructurado, ....

Por otra parte, podeis ver cómo la vista no está estructurada como clase AS2, ya que no parece necesario hacerlo. Es una de las cosas que me encantan de flash. Podemos mezclar código en uno u otro estandar, dependiendo de lo que nos interese en cada momento....

Descarga el código fuente y el fla aquí

Comentarios

Gracias por su explicacion pero seria conveniente que nos indiquen nombres de libros donde se pueda consultar.
Agradeceria mucho si me proporcionara el nombre de algun libro.

Por supuesto.

El libro por excelencia sobre patrones de diseño es "Patrones de diseño", por L. Gamma y otros, que está editado en castellano ( y barato ) por la editorial Addison-Wesley ( al menos en España ). A este libro se le conoce como el "Gang of Four", y es el libro de referencia a la hora de hablar de patrones de diseño.

Espero que te resulte de utilidad...