![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Buscar | Temas de Hoy | Marcar Foros Como Leídos |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
#8
|
||||
|
||||
|
Cita:
Es cierto que implica más trabajo pero no donde estás pensando. Te pongo una idea un poco más explícita. Considera primero estas definiciones de clases:
TDataQuery representa un Query genérico, tal como lo describí antes. Aquí, los métodos SetXXX establecen valores de parámetros mientras que los métodos GetXXX devuelven valores de campos una vez ejecutada la consulta. Es decir, lo equivalente a las propiedades Params y Fields de un Query. Como antes, todos estos métodos junto con Run (que abre o ejecuta la consulta) y First, Next y EoQ (para navegación) son abstractos y cada descendiente debe implementarlos. Ahora bien, los objetos Query los produce un objeto DataConnection con su método NewQuery. DataConnection representa una conexión a un servidor; de ahí sus propiedades User, Password y Database. La propiedad Params serviría para establecer otro tipo de parámetros según sea el caso. TDataConnection también es una clase con métodos abstractos. Un objeto DataConnection lo produce un objeto DataClient con su método NewConnection. DataClient englobaría todo lo que sea común a conexiones a servidores del mismo tipo. Para cada motor que pienses usar necesitarás crear descendientes adecuados, por ejemplo:
TZeosDataClient implementará NewConnection para producir un objeto TZeosDataConnection. TZeosDataConnection implementará NewQuery para producir un objeto TZeosDataQuery. TZeosDataQuery implementará los métodos SetXXX, GetXXX, Run y de navegación (posiblemente tomándolos de un TZQuery). Ahora bien; tú puedes, como dices, tener cien objetos DataQuery en tu aplicación; pero si todos los produces con TDataConnection.NewQuery, el día que quieras cambiar el motor que uses, sólo tienes que cambiar la creación del DataConnection específico, que normalmente sólo será uno a menos que ataques varios servidores a la vez. Aún en este caso no importa, porque los objetos DataConnection son producidos por un objeto DataClient genérico, del cuál sólo habrá uno por motor, digamos ZeosDataClient, encargado de producir cualquier conexión vía Zeos. En resumen, el curso de tu aplicación podría ser:
Cuando cambies de motor, digamos a Firebird, únicamente debes cambiar la línea GlobalDataClient := TZeosDataClient.Create; por GlobalDataClient := TFirebirdDataClient.Create; Todos los objetos DataConnection que hayas creado en tu aplicación serán ahora creados por TFirebirdDataClient.Connection (por el polimorfismo) y todos los objetos DataQuery que uses serán ahora creados por TFirebirdDataConnection (otra vez por el polimorfismo). Claro que para ello deberás implementar TFirebirdDataClient, TFirebirdDataConnection y TFirebirdDataQuery, pero esto lo haces una sóla vez y sin tocar la aplicación principal excepto por la línea susomentada ( )--------------------- Todo esto son sólo ideas al aire y ciertamente no originales y susceptibles de cambios. Por ejemplo, todos los objetos producidos por NewConnection y NewQuery tendrán que ser destruídos en algún momento. Por ello, en lugar de clases abstractas yo usaría interfaces para aprovechar su autodestrucción. En lugar de GetXXX podrías publicar una función abstracta en la clase base que devuelva un TDataSet que puedes conectar a tus controles DBAware. No me gusta mucho esto último pues TDataSet tiene muchos métodos y propiedades que de alguna manera te permiten actuar directamente con la base de datos con lo cual puedes perder un poco de control. En todo caso podría usarse un TClientDataSet llenado internamente por DataQuery. Lo importante aquí es simplemente el hecho de poder cambiar de un motor a otro sin- en teoría -grandes cambios. Yendo más lejos. Para cambiar de motor debes, como dije, cambiar la línea GlobalDataClient := TZeosDataClient.Create; pero puedes hacer uso de una fabrica de clientes:
Usando un TStringList, por ejemplo, puedes guadar una asociación entre un identificador y la clase de cliente correspondiente, por ejemplo: 'zeos' => TZeosDataClient El método RegisterClient('zeos', TZeosDataClient) guardaría dicha asociación de manera que puedes obtener un objeto DataClient partiendo del identificador: GlobalDataClient := DataClientFactory.NewClient('zeos'); El método NewClient construiría el objeto DataClient polimórficamente partiendo de la referencia de clase asociada a la cadena 'zeos':
Cada motor que implementes deberá hacer uso de DataClientFactory.RegisterClient para registrar su case de objeto DataClient; por ejemplo en la sección initialization de la unidad donde implementes las clases del motor. Suponte ahora que todas las clases asociadas a un motor las colocas dentro de un paquete. Si usas paquetes dinámicos puedes cargar el paquete asociado a un motor en tiempo d ejecución partiendo sólo del identificador del cliente ('zeos' por ejemplo), de manera que puedes añadir motores sin necesidad siquiera de recompilar la aplicación principal. // Saludos Última edición por roman fecha: 02-09-2005 a las 06:46:02. |
| Herramientas | Buscar en Tema |
| Desplegado | |
|
|
|