Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-07-2008
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
Como instanciar objetos de los cuales solo se conoce su clase ancestro

Estoy jugando al modelo MVC

Tengo un objeto TController que gestion acciones y algunas reglas de negocio, a este TController actualmente le paso varios descendientes de TForm para que los utilice cuando le haga falta de manera que mi pseudo código queda así:

Instanciar el controlador
Instanciar las vistas que va a usar el controlador
Pasarle las vistas creadas al controlador.


El controlador en este caso solo sabe que las vistas con TForms o sus descendientes, como es obvio estos TForms siempre son descendientes de TForm. Como lo tengo tengo que instanciar primero las TForms y luego pasarlas al Controlador, lo que quisiera es que el controlador fuera capaz de instanciar correctamente cada TForm según lo necesite.

Como el controlador no sabe que clase realmente representa cada TForm no es capaz de llamar al constructor correcto.

Lo más simple sería modificar rápidamente al controlador para que llame al constructor correcto según el caso, pero lo que quiero es que el controlador sea totalmente independiente de la forma que le pase uno y que llame al constructor que corresponda.

Se aceptan sugerencias.
__________________
AKA "El animalito" ||Cordobés a mucha honra||
Responder Con Cita
  #2  
Antiguo 07-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Azid, después te pasas por la taberna

Bueno, con respecto al Modelo MVC no lo he llevado a la práctica exactamente y por lo que comprendo (de lo poco que estuve leyendo sobre este modelo) se basa en la idea del Observador.

Por lo que comprendo... una vista notifica (envia un mensaje) al controlador y éste aplica los cambios al modelo. Y si es necesario notificar de algo a la vista, el controlador le hace notificar de ello.

En principio, pareciera ser que el controlador no sabe con que vistas interactuará. Y si es así, lo único que conoce es una "interfaz" común a ellas.
Por lo general, en principio, una implementación de este tipo de patrón lo que hace es que el Controlador mantenga una referencia de los objetos vistas... Yo lo veo así: las vistas se suscriben al controlador. Y éste cuando sea necesario, recorre todos los objetos registrados lanzando el evento adecuado pasando como parámetro el "valor" que sea necesario.

La implementación del evento queda a cargo de cada vista.

Si es asi como debería actuar, me parece entonces que el Controlador no es el experto en información adecuado para crear las vistas. Más bien, el no tiene pleno conocimiento de quienes son ni que hacen. Simplemente el les hace saber que "algo cambió"

Por tu descripción del tema, pareciera ser que lo que deseas es implementar una fábrica de vistas.

Y si uno ideas, pareciera ser que el tema puede venir así:
1. Se cre el controlador
2. Se crea la Fábrica
3. la Fábrica crea la vista
4. La vista creada se registra en la "colección" del Controlador para que este le notifique de los cambios.

Ahora el tema de como hacer la referencia desde la vista al controlador, pareciera ser que sería apropiado que la vista tenga visibilidad de atributo sobre el Conntrolador...

Código Delphi [-]
TVista = class(TForm)
private
  Controler : TControler;
  ...

De modo que cuando desee enviarle un mensaje, la vista pueda recuperar dicha referencia.

Tal vez, sea la fábrica quien le indique a la vista a que controlador referenciar. Por lo poco que se, me resulta que es una buena candidata. Me parece adecuado, al menos por ahora, que al momento de crear la vista, la fábrica le haga saber el controlador. Por lo pronto, yo me hago la idea de esto:

Código Delphi [-]
constructor TVista.Create(Controler: TControler);
begin
  inherited Create;
  FControler := Controler;
  ...
end;

Si el tema de la fábrica es lo que se debería seguirse, me queda ahora la duda ¿Quién es el dueño realmente de las vistas? Una respuesta rápida me indicaría que es TAplication. Después de todo... ¿No es él quien tiene y guarda la referencias a todas la formas que componen a la aplicación?

Pero no se que tan viable, y aplicable, sea esta idea. Reconozco que el patrón Observador y el MVC son todavía de estudio para mi.

No se si te he ayudado o confundido más. Disculpame amigo, pero más no sabría decirte. Tengo que estudiarlo mejor al patrón.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #3  
Antiguo 07-07-2008
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola César!

Primero que nada, acá te esperamos, la fiesta durará hasta el martes : http://www.clubdelphi.com/foros/showthread.php?t=58049

No sé mucho de modelos (casi todo lo programo según los astros ). Pero me salta la siguiente pregunta al leer tu planteamiento:

¿No te sirve pasarle al controlador la clase de objeto que deseas instanciar? Algo así como:
Código Delphi [-]
Controlador.SetView (TfmCliente);

Dentro del método SetView, el objeto controlador podría ejecutar la instanciación sin problemas:
Código Delphi [-]
Procedure TControlador.SetView (Const Clase :TFormClass);
Var
  F :TForm;
Begin
  { En lugar de Nil, puede especificarse otro valor como "Owner"
    (por ejemplo Self si TControlador es descendiente de
    TComponent) }
  F := Clase.Create (Nil);
  
  { Hacer x cosa con la instancia F }
End;

Recuerda que también los métodos constructores pueden ser virtuales, y ese es el caso del constructor Create que TForm hereda de la clase TComponent. Por lo tanto se estará llamando al constructor que corresponda en caso de que lo hayas redefinido (Override) en algunas de tus clases de formularios.

Espero te resulte oportuna mi aportación. No dejes de comentarnos sobre tus avances.

Saludos.

Al González.
Responder Con Cita
  #4  
Antiguo 07-07-2008
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.278
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por AzidRain Ver Mensaje
Como el controlador no sabe que clase realmente representa cada TForm no es capaz de llamar al constructor correcto.

Lo más simple sería modificar rápidamente al controlador para que llame al constructor correcto según el caso, pero lo que quiero es que el controlador sea totalmente independiente de la forma que le pase uno y que llame al constructor que corresponda.
Bueno, independientemente de tu modelo, sólo se me ocurren dos formas de hacer eso:
(1) A partir del nombre y intentando obtener la referencia a la clase utilizando RTTI; Ya lo hemos discutido muchas veces por aquí.
(2) Teniendo en algun sitio un "diccionario" (que no deja de ser algo simnilar a lo que hace RTTI) que sirve de "apoyo" a tu controlador donde tengas todas las instancias y sus constructores.

Código Delphi [-]
 
    // Definición de la instancia
TInstancia1 = class(TForm)
    ....

Código Delphi [-]
   Type
      // Tipo apuntador al constructor
     TFormInstancia1Class = class of TInstancia1;

En tu diccionario debes guardar los apuntadores; En mi caso suelo guardar una pareja, ID+ApuntadorConstructor. Con ese diccionario el controlador puede crear las instancias del tipo correcto.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #5  
Antiguo 10-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Azid,
¿Lograste avanzar en algo? ¿Tienes novedades?

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #6  
Antiguo 11-07-2008
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
Finalmente conseguí que funcionara el modelado como lo había concebido, aunque creo que todavía puede mejorarse y obviamente no es nada del otro mundo.

Es un modelo simple para manejar una tabla o query que represente un catálogo, es decir, esas formas que muestran en un grid todos los registros de la tabla. Este tipo de ventanas son muy comunes en programas administrativos y en uno que estoy haciendo requiero hacer lo mismo muchísimas veces, cambiando solamente el catálogo en cuestión.

Asi que para armar un catálogo completo necesitamos:

1.- Controlador de Grid (o grilla)
2.- Una vista (forma) principal (la que tiene el grid)
3.- Una vista (forma) para editar un registro (que es la misma para cambiarlo)
4.- Un modelo (tabla) que representa los datos a visualizar

En clases es así:
1.- TdxGridControlador
2.- TdxGridForm
3.- TdxDialogForm
4.- TZquery + TDataSource [+ TUpdateSQL si usamos un query multitablas]

TdxGridView se vé así:
[IMG] http://img133.imageshack.us/img133/4645/dxgridht4.jpg [/IMG]

y TdxDialogForm se vé así:



Pues bien la cosa es así:

Tenemos una clase TdxControlador que es la clase base para construir diferentes tipos de controladores simples. De ahi derivé TdxGridControlador que es un controlador especializado en manejar un grid y hacer las famosas Altas-Bajas-Modificaciones, esta sería su declaración:

Código Delphi [-]

TAuxForma = Class of TTdxDialogForm;

TdxGridControlador = class(TdxControlador)
Public
TablaDatos:TDataset;

constructor Create( ClaseForma : TClassForm);override;
procedure OnNuevoRegistro(sender:TObject);virtual;abstract;
procedure OnCambiarRegistro(sender:TObject);virtual; abstract;
procedure OnBorrarRegistro(sender:TObject);virtual;

procedure OnBotonOk(sender:TObject); override;
procedure OnBotonCancel(sender:TObject);override;



protected
Procedure EnNuevo(aForm:TAuxForma);virtual;
Procedure EnEdita(aForm:TAuxForma);virtual;

end;

Como podemos ver se trata prácticamente de enventos, que serán disparados de acuerdo con el diseño de que se trate. Tanto OnNuevoRegistro como OnCambiaRegistro son métodos abstractos por lo que hay que definir que queremos que pase en cada caso. Por su parte OnBotonOk y OnBotonCancel son métodos que se ejecutan cuando aparecen los diálogos para un nuevo registro (TdxDialogForm) o para cambiarlo.

Para utilizar todo este andamiaje, veamos un ejemplo para una tabla Empleados, hacemos lo siguiente:

1.- Crear el query en un datamodule y prepararlo como se requiera, aquí podemos incluir condiciones para nuevos campos, chequeo de índices, etc. lo que normalmente se hace.

2.- Crear la vista principal derivando una nueva forma de TdxGridForm y ajustamos los valores del Grid (en mi caso ocupo mis amadas DevExpress pero con un grid normal funciona igual) para utilizar el query que creamos anteriormente (databinding). Es importante ver que este query contiene un TActionList que ya está preparado para trabajar con el controlador por lo que no hay que tocar nada de eventos. Se llamara TFCatEmpleados:


3.- Creamos la vista o vistas para Agregar o editar un registro, colocamos los controles que necesitemos y hacemos nuevamente databinding con la misma query.Se llamará TFNuevoEmpleado.:



4.- Finalmente preparamos el controlador derivando una nueva clase a partir de TdxGridControlador, únicamente tenemos que indicarle de que clase son las formas que utilizaremos para la edición de registros.

Código Delphi [-]

Type
TCEmpleados = class(TdxGridControlador)

Procedure CierraForma(sender:TObject);

{*** Eventos para la vista principal ***}

procedure OnNuevoRegistro(sender:TObject);override;
procedure OnCambiarRegistro(sender:TObject);override;


end;

implementation

{ TCEmpleados }

procedure TCEmpleados.CierraForma(sender: TObject);
begin

end;

procedure TCEmpleados.OnCambiarRegistro(sender: TObject);

begin
EnEdita(TFNuevoEmpleado);
end;

procedure TCEmpleados.OnNuevoRegistro(sender: TObject);
Begin
EnNuevo(TFNuevoEmpleado);
end;

end.

implementation

end.

5.- En la parte del programa donde vamos a utilizar este andamiaje preparamos todo y lo ejecutamos:

Código Delphi [-]

procedure TMainForm.AEmpleadosExecute(Sender: TObject);
var cE: TCEmpleados;

begin
{Crear el controlador y pasarle la vista principal}

cE := TCEmpleados.create( TFCatEmpleados );
ce.TablaDatos.Open;
Datos.ZPuestos.Open; //Tabla auxiliar para los puestos
Try
ce.MuestraVistaPrincipal;
Finally
Datos.ZPuestos.Close;
ce.TablaDatos.Close;
ce.Free;

end;

end;
Y obtenemos esto:

Al hacer click por ejemplo en Editar, obtendremos:


Igualmente con nuevo. El botón de borrar por defecto lo único que hace es preguntar si se está seguro y borrar el registro actual.

Asi de simple, no hay que hacer nada adicional, claro si se de desea se pueden extender más las clases y agregar más cosas, pero así como está me sirve y me mantiene un orden más o menos adecuado en lo que voy haciendo.

Y claro...no es el hilo negro eh...que conste.
__________________
AKA "El animalito" ||Cordobés a mucha honra||
Responder Con Cita
  #7  
Antiguo 11-07-2008
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
A ver si algun moderador me compone el post porque otra vez no funcionan las etiquetas para poner imágenes...me lleva.. me tarde 30 minutos para escribir todo, sacar las pantallas, subirlas, pegarlas para que al final esta mugre de VBulletin no sirva...
__________________
AKA "El animalito" ||Cordobés a mucha honra||
Responder Con Cita
  #8  
Antiguo 11-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Me alegro mucho de que hayas logrado resolver tu problema.
Gracias por compartir con nosotros la solución que planteaste, tendré en cuenta tu aporte para continuar con mi investigación y estudio sobre esta área (la cual admito que es una zona gris en mi mar del conocimiento).

No te hagas drama por las imágenes. Está disponible el enlace. Lo importante es que lograste avanzar.

Saludos amigo,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Crear una clase y asignar objetos como propiedades leanfreue OOP 4 13-04-2007 00:08:33
Instanciar Clase buildero_d OOP 2 05-10-2006 06:12:56
¿alguien conoce el uso de la clase TOwnerCollection? fredo OOP 11 01-08-2005 18:05:56
¿Cómo puedo llamar al método heredado de una clase que no es el ancestro directo? sarackganda OOP 4 15-12-2003 22:19:49
Obtener la clase de objetos Feñiz OOP 7 08-05-2003 20:21:55


La franja horaria es GMT +2. Ahora son las 03:22:13.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi