La mise en œuvre des ensembles d'objets


Dans cet article, je continue mon look à la mise en œuvre des ensembles d'objets.
Concis Personnalisé Constructeurs
Dans mon dernier article, j'ai défini les grands principes qui sous-tendent la mise en œuvre des ensembles d'objets avec un problème de domaine de classe orientée à agir comme un conteneur pour l'entreprise les objets eux-mêmes. Cela s'est fondée sur une étendue de données de gestion de classe qui pourrait soutenir la navigation dans une base de données dépendant de curseur d'une certaine sorte. Ce mois-ci conclut cette enquête en fournissant plus de détails de mise en œuvre et nous voyons que, une fois l'application indépendante de cadre a été fourni, le code requis pour un système réel est très faible.
Nous avons déjà vu, l'interface proposée pour notre classe qui gère l'ensemble de business objects, TPDList. Ce classique a d'Abord, Ensuite et IsLast méthodes de travail de délégué à un privé de la gestion des données de l'objet, qui est construit en fonction des besoins de la liste en question. Voici le code de notre base de TPDList constructeur:
constructeur TPDList.Créer (ListDMObject: TDMObject)
begin
& nbsp & nbsp hérité de Créer // constructeur Standard
& nbsp & nbsp DMObject := ListDMobject // référence Privée
fin
Ce code indique que le constructeur s'attend à être passé d'une gestion de données de l'objet en tant que paramètre. Ce devrait être du type correct pour soutenir la liste des opérations pour la classe en question, et sera assurée par l'application spécifique de la liste de constructeur. Une fois cette gestion des données de l'objet a été transmis à notre liste, il en assume l'entière responsabilité et doit donc libre dans le destructeur. Cela rompt une bonne habitude de la règle générale, là où une classe doivent être détruits dans la portée et le contexte dans lequel il a été créé, mais il ne permet pas pour autant concis de codage qui facilite la tâche lors de la mise en œuvre de ces classes dans une application.
Listing 1 montre la réelle mise en œuvre d'un TCustomerList classe qui a un certain nombre de constructeurs. Comme on peut le voir chaque constructeur personnalisé appelle tout simplement la norme héritée constructeur, dynamique de la construction de la gestion de données de l'objet requis. Un point particulier est que les paramètres sont passés inchangées pour la deuxième constructeur, en gardant l'interface entre la logique métier et les classes de persistance de la base de données neutre. En dehors de la propriété qui renvoie le 'courant' du domaine du problème de l'objet dans la liste catalogué à l'un d'un type approprié, c'est toute la mise en œuvre que de la logique de gestion des besoins pour chaque nouveau type de liste nécessaires. Comme on peut le voir, c'est une très petite quantité de code, comme la plupart des travaux qui se passe dans notre application indépendante des classes de base.
l'Encapsulation des Accès de Base de données
La raison pour laquelle notre logique d'entreprise pour la gestion de ces listes est tellement légère est parce qu'ils déléguer tout le travail de leurs données respectives des objets de gestion. Selon la base de données qui est utilisé pour sauvegarder les données de l'objet, la quantité de travail nécessaire ici peuvent varier énormément. Heureusement, la grande majorité des systèmes, ces jours-ci stockent leurs données dans un SGBD, ou au moins avoir accès aux données par l'intermédiaire d'un langage de requête, auquel cas la mise en œuvre est simple.
Nos données de gestion de la classe aura besoin d'un privé curseur de quelque sorte à la base de données. Je suis en supposant que ce curseur (dans cet exemple) a la possibilité d'exécuter une requête SQL, et de récupérer les données. Ce curseur sera évidemment de la base de données entièrement dépendant généralement je choisis le plus rapide, le plus pratique ou le plus facile à déployer option pour une base de données. Cela pourrait être une API générique comme ADO et ODBC, ou plus généralement, j'utilise une approche spécifique, comme par exemple une interface à un client de l'API, peut-être l'aide d'un wrapper mince (comme IBExpress pour Interbase d'accès). Certains peuvent se demander pourquoi ne pas construire la base de données entièrement couche autour d'une base de données existante-indépendant de l'API telles que ODBC. Il n'y a rien à dire que ce n'est pas une solution viable, mais en gardant à l'interface de la couche de base de données entièrement neutre (et objet) a l'avantage de permettre à tous ces API est d'être utilisé, le cas échéant. La mise en œuvre effective de la couche de base de données est bien sûr libre d'utiliser les API, il choisit de le faire, y compris les génériques telles que ADO, ODBC ou BDE. Il convient de souligner que le fait de fournir notre propre base de données-interface neutre pour la persistance d'objet n'est pas de réinventer la roue, notre interface est très léger (wrapper souvent mis en œuvre comme le patron de la Façade) autour d'une plus fonctionnelles de l'API à laquelle la majeure partie du travail est délégué. La clé est que notre wrapper encapsule les fonctionnalités requises, et facilite la sélection d'une autre base de données de l'API doivent modifier les exigences ou besoins.
La FirstRecord méthode de notre classe (appelée par la Première méthode dans le TPDList) tout simplement annule toute l'exécution de la requête au sein de la classe et les questions appropriées de la requête SELECT. Le NextRecord sera mappée sur une méthode appropriée, sur la base de données de curseur, de même que les IsLast de la propriété. Comme chaque enregistrement dans le curseur est accessible, la gestion des données de la classe doit être prêt à instancier et de remplir un professionnel approprié de l'objet prévu par l'appel TPDList. La population de cette classe à partir de la base de données curseur champs doivent être partagés avec la population d'un même objet par le biais de la méthode de Chargement, et est le mieux réalisé par l'appel d'une méthode abstraite, en passant le curseur base de données et l'objet à être peuplée. Cette méthode doit être remplacée par notre application de gestion de données spécifiques des objets à fait de mise à jour des propriétés connues de l'activité objet de champs nommés dans la curseur.
Nous avons déjà indiqué que notre gestion des données de classes possèdent des constructeurs qui correspondent à ceux de leur problème de domaine de la liste des équivalents. En supposant que notre base de données prend en charge les requêtes, tous ces constructeurs ont besoin pour faire est de définir une chaîne de requête qui sélectionne les enregistrements requis à partir de la table, dynamique de la construction de la requête à partir des paramètres de transmission. Pour les requêtes qui sont exécutées très fréquemment, ou dont le rendement est primordial, il est bien sûr possible pour ce constructeur à appeler une procédure stockée personnalisée sur la base de données, d'un passage de paramètres par le biais d'une forme commode (telles que le remplacement d'ID d'objet pour les objets référencés passé en paramètre). Le FirstRecord méthode dans notre classe sera effectivement chargé de lancer l'exécution de la requête (ou l'appel d'une procédure stockée) c'est une bonne pratique car elle maintient le constructeur d'une classe léger. Le Listing 2 présente les constructeurs correspondants pour la CustomerDM (gestion des données) de l'objet.
Hiérarchies de responsabilité

je doit enfin passer de commentaire sur la hiérarchie de classes impliquées dans la gestion des données secondaires. Notre base de TDMObject doivent être conservés base de données indépendante, mais il doit fournir une interface que le problème de domaine de classes peuvent utiliser. Ceci est réalisé en fournissant un certain nombre de méthodes abstraites de la classe. La base de données réelle dépendances sont introduits dans des descendants de TDMObject (comme TSQLServerDMObject, ou TOracleDMObject) qui mettent en œuvre les méthodes abstraites, pour fournir les services nécessaires à l'appui de la base de données access à l'encontre de leur plate-forme cible, et peut fournir d'autres méthodes abstraites qui doivent être mises en œuvre par les descendants.
Ces bases de données descendants sont parfaitement en droit d'introduire des dépendances sur toutes les autres classes, ils ont besoin de communiquer avec leur base de données à l'aide des API. En général, ils fournissent une quantité raisonnable de la fonctionnalité de l'appui des questions telles que l'établissement d'une connexion au moteur, la sélection d'une base de données spécifique, vous connecter comme utilisateur nommé et ainsi de suite. La façon dont ils atteindre de tels besoins est entièrement sous leur propre contrôle: n'oubliez pas que notre base TDMObject interface est un contrat purement pour les services requis par le TPDObject et TPDList, et ne dicte pas de détails comme un contexte de base de données. Cela signifie également que notre base de données d'objets spécifiques peuvent tirer parti de toutes les caractéristiques de la base de données ou API pour maximiser la facilité d'utilisation ou de la performance, tout en se reposant tout en sachant qu'un passage à une autre base de données est toujours possible sans de gros changements dans le corps principal de l'application du code. En fait, comme ces classes sont indépendantes des applications, il est possible pour un expert base de données à intégrer éventuellement des niveaux élevés de complexité (pour extraire le maximum de performance à partir de l'API), tout en exposant une interface simple pour les applications spécifiques des utilisateurs de ces classes.
l'Un des effets secondaires de cette hiérarchie, c'est que notre application de gestion des données des objets sera fortement liée à la fonctionnalité requise d'une base de données spécifique de la couche, et par conséquent un changement de base de données requiert une ré-implémentation de la gestion des données des objets. Cet impact peut être réduit ou peut-être même complètement supprimée si la base de données des classes spécifiques sont conçus avec les mêmes services de l'expérience suggère que, même si cette approche est pratique pour les mêmes API de base de données, en fournissant une base de données entièrement indépendant de la hiérarchie de classe limite les possibilités de tirer parti d'une plate-forme spécifique. Bien entendu, il est parfaitement possible d'introduire des sous-hiérarchies à l'identique les interfaces, les plus courants étant un ensemble d'objets de base de données qui utilisent SQL comme leur principal moyen de communication. Cela se prête à des hiérarchies telles que les suivantes, où les trois premières catégories se trouvent à l'intérieur du cadre (et inclure la majeure partie du code), et les deux dernières classes sont spécifiques à l'application:
TDMObject & #8594 TSQL_DMObject & #8594 TOracleDMObject & #8594 TMyAppDMObject & #8594 TCustomerDM
Dernier article de la question
j'ai demandé comment nous pouvons utiliser notre nouvelle liste des classes pour représenter les relations d'objet tel que 1-de nombreuses. Un exemple classique d'une telle relation Client.Les commandes, représentant l'ensemble des commandes déjà passées par un client. Comme avec nos autres 1-1 et beaucoup d'-1 relations, de les exposer à la propriété des classes est une agréable et moyen naturel de le faire. La première question est, comment peuvent-ils être mis en œuvre? La réponse à cela est très simple, nous allons utiliser la norme paresseux techniques de construction sur notre propriété la fonction d'accès à seulement créer la liste de la première fois qu'il est nécessaire. La liste réelle de être construits seront la liste appropriée en fonction de la relation que nous formulons, dans ce cas, nous voulons construire la liste des Commandes d'un Client connu. Le Listing 3 montre une mise en œuvre complète d'une telle relation. Le plus révélateur caractéristique est l'utilisation de 'Auto' pour construire une liste de Commandes pour un Client spécifique de l'instance.
La deuxième partie de la question était: peut-on gérer ces opérations de manière générique, comme nous le faisons avec le plus simple des relations (rappelez-vous, nous avons implémenté un générique de la méthode GetObject dans notre base TPDObject classe)? Sur le visage de celui-ci, nous pourrions être en mesure de mettre en œuvre un générique GetList méthode, mais sur une inspection plus minutieuse, ce n'est pas le cas. La raison de cette incapacité à gérer les listes de façon générique, c'est que nous voulons appeler un constructeur avec paramètres particuliers sur la liste nécessaire. Cela nécessiterait une sorte de référence à un constructeur de type, et il n'y a pas de manière concise d'exprimer ce, tout en conservant la gestion des paramètres simples. Ainsi, alors que l'on peut gérer seul les relations d'objet générique nous ne pouvons pas faire la même pour définir les relations d'objet et ils doivent tous être traités de façon explicite comme vu dans le Listing 1. Comme on le voit, la quantité de code est minime et ce n'est donc pas trop lourd tâche.
((( Listing 1 - Personnalisé constructeurs pour TCustomerList)))
constructeur TCustomerList.CreateAll
begin
& nbsp & nbsp hérité de Créer (TCustomerDM.CreateAll)
fin
constructeur TCustomerList.CreateByName (const Nom: String)
begin
& nbsp & nbsp hérité de Créer (TCustomerDM.CreateByName (Nom))
fin
constructeur TCustomerList.CreateByStockOrder (Item: TStockItem)
begin
& nbsp & nbsp hérité de Créer (TCustomerDM.CreateByStockOrder (Item))
fin
((( Fin Listing 1 )))
((( Listing 2 - Correspondance des constructeurs pour le Client de Gestion de Données objet)))
constructeur TCustomerDM.CreateAll
begin
& nbsp & nbsp hérité de Créer
& nbsp & nbsp Requête := 'SELECT * from Client ORDER BY Nom'
fin
constructeur TCustomerDM.CreateByName (const Nom: String)
begin
& nbsp & nbsp hérité de Créer
& nbsp & nbsp Requête := 'SELECT * from Client where Nom LIKE '' Nom '%'
fin
constructeur TCustomerDM.CreateByStockOrder (Item: TStockItem)
begin
& nbsp & nbsp hérité de Créer
& nbsp & nbsp Requête := 'SELECT * from Client where ItemID=' IDToStr (Item.ID)
fin
((( Fin de Liste 2 )))
& nbsp ((( Listing 3 - mise en Œuvre 1-nombre de relations )))
type
& nbsp & nbsp TCustomer = classe (TPDObject)
& nbsp & nbsp privé
& ! & ! & ! & nbsp FOrders: TOrderList
& ! & ! & ! & nbsp fonction GetOrders: TOrderList
& nbsp & nbsp public
& ! & ! & ! & nbsp destructeur de Détruire remplacer
& ! & ! & ! & nbsp propriété Commandes: TOrderList lire GetOrders
& nbsp & nbsp fin
destructeur TCustomer.Détruire
begin
& nbsp & nbsp FOrders.Gratuit
& nbsp & nbsp hérité
fin
fonction de TCustomer.GetOrders: TOrderList
begin
& nbsp & nbsp si FOrders = nil alors FOrders := TOrderList.CreateByCustomer (Auto)
& nbsp & nbsp Résultat := FOrders
fin
((( Fin Listing 3 )))









La mise en œuvre des ensembles d'objets


La mise en œuvre des ensembles d'objets : Plusieurs milliers de conseils pour vous faciliter la vie.


Dans cet article, je continue mon look a la mise en œuvre des ensembles d'objets.
Concis Personnalise Constructeurs
Dans mon dernier article, j'ai defini les grands principes qui sous-tendent la mise en œuvre des ensembles d'objets avec un probleme de domaine de classe orientee a agir comme un conteneur pour l'entreprise les objets eux-memes. Cela s'est fondee sur une etendue de donnees de gestion de classe qui pourrait soutenir la navigation dans une base de donnees dependant de curseur d'une certaine sorte. Ce mois-ci conclut cette enquete en fournissant plus de details de mise en œuvre et nous voyons que, une fois l'application independante de cadre a ete fourni, le code requis pour un systeme reel est tres faible.
Nous avons deja vu, l'interface proposee pour notre classe qui gere l'ensemble de business objects, TPDList. Ce classique a d'Abord, Ensuite et IsLast methodes de travail de delegue a un prive de la gestion des donnees de l'objet, qui est construit en fonction des besoins de la liste en question. Voici le code de notre base de TPDList constructeur:
constructeur TPDList.Creer (ListDMObject: TDMObject)
begin
& nbsp & nbsp herite de Creer // constructeur Standard
& nbsp & nbsp DMObject := ListDMobject // reference Privee
fin
Ce code indique que le constructeur s'attend a etre passe d'une gestion de donnees de l'objet en tant que parametre. Ce devrait etre du type correct pour soutenir la liste des operations pour la classe en question, et sera assuree par l'application specifique de la liste de constructeur. Une fois cette gestion des donnees de l'objet a ete transmis a notre liste, il en assume l'entiere responsabilite et doit donc libre dans le destructeur. Cela rompt une bonne habitude de la regle generale, la ou une classe doivent etre detruits dans la portee et le contexte dans lequel il a ete cree, mais il ne permet pas pour autant concis de codage qui facilite la tache lors de la mise en œuvre de ces classes dans une application.
Listing 1 montre la reelle mise en œuvre d'un TCustomerList classe qui a un certain nombre de constructeurs. Comme on peut le voir chaque constructeur personnalise appelle tout simplement la norme heritee constructeur, dynamique de la construction de la gestion de donnees de l'objet requis. Un point particulier est que les parametres sont passes inchangees pour la deuxieme constructeur, en gardant l'interface entre la logique metier et les classes de persistance de la base de donnees neutre. En dehors de la propriete qui renvoie le 'courant' du domaine du probleme de l'objet dans la liste catalogue a l'un d'un type approprie, c'est toute la mise en œuvre que de la logique de gestion des besoins pour chaque nouveau type de liste necessaires. Comme on peut le voir, c'est une tres petite quantite de code, comme la plupart des travaux qui se passe dans notre application independante des classes de base.
l'Encapsulation des Acces de Base de donnees
La raison pour laquelle notre logique d'entreprise pour la gestion de ces listes est tellement legere est parce qu'ils deleguer tout le travail de leurs donnees respectives des objets de gestion. Selon la base de donnees qui est utilise pour sauvegarder les donnees de l'objet, la quantite de travail necessaire ici peuvent varier enormement. Heureusement, la grande majorite des systemes, ces jours-ci stockent leurs donnees dans un SGBD, ou au moins avoir acces aux donnees par l'intermediaire d'un langage de requete, auquel cas la mise en œuvre est simple.
Nos donnees de gestion de la classe aura besoin d'un prive curseur de quelque sorte a la base de donnees. Je suis en supposant que ce curseur (dans cet exemple) a la possibilite d'executer une requete SQL, et de recuperer les donnees. Ce curseur sera evidemment de la base de donnees entierement dependant generalement je choisis le plus rapide, le plus pratique ou le plus facile a deployer option pour une base de donnees. Cela pourrait etre une API generique comme ADO et ODBC, ou plus generalement, j'utilise une approche specifique, comme par exemple une interface a un client de l'API, peut-etre l'aide d'un wrapper mince (comme IBExpress pour Interbase d'acces). Certains peuvent se demander pourquoi ne pas construire la base de donnees entierement couche autour d'une base de donnees existante-independant de l'API telles que ODBC. Il n'y a rien a dire que ce n'est pas une solution viable, mais en gardant a l'interface de la couche de base de donnees entierement neutre (et objet) a l'avantage de permettre a tous ces API est d'etre utilise, le cas echeant. La mise en œuvre effective de la couche de base de donnees est bien sûr libre d'utiliser les API, il choisit de le faire, y compris les generiques telles que ADO, ODBC ou BDE. Il convient de souligner que le fait de fournir notre propre base de donnees-interface neutre pour la persistance d'objet n'est pas de reinventer la roue, notre interface est tres leger (wrapper souvent mis en œuvre comme le patron de la Façade) autour d'une plus fonctionnelles de l'API a laquelle la majeure partie du travail est delegue. La cle est que notre wrapper encapsule les fonctionnalites requises, et facilite la selection d'une autre base de donnees de l'API doivent modifier les exigences ou besoins.
La FirstRecord methode de notre classe (appelee par la Premiere methode dans le TPDList) tout simplement annule toute l'execution de la requete au sein de la classe et les questions appropriees de la requete SELECT. Le NextRecord sera mappee sur une methode appropriee, sur la base de donnees de curseur, de meme que les IsLast de la propriete. Comme chaque enregistrement dans le curseur est accessible, la gestion des donnees de la classe doit etre pret a instancier et de remplir un professionnel approprie de l'objet prevu par l'appel TPDList. La population de cette classe a partir de la base de donnees curseur champs doivent etre partages avec la population d'un meme objet par le biais de la methode de Chargement, et est le mieux realise par l'appel d'une methode abstraite, en passant le curseur base de donnees et l'objet a etre peuplee. Cette methode doit etre remplacee par notre application de gestion de donnees specifiques des objets a fait de mise a jour des proprietes connues de l'activite objet de champs nommes dans la curseur.
Nous avons deja indique que notre gestion des donnees de classes possedent des constructeurs qui correspondent a ceux de leur probleme de domaine de la liste des equivalents. En supposant que notre base de donnees prend en charge les requetes, tous ces constructeurs ont besoin pour faire est de definir une chaîne de requete qui selectionne les enregistrements requis a partir de la table, dynamique de la construction de la requete a partir des parametres de transmission. Pour les requetes qui sont executees tres frequemment, ou dont le rendement est primordial, il est bien sûr possible pour ce constructeur a appeler une procedure stockee personnalisee sur la base de donnees, d'un passage de parametres par le biais d'une forme commode (telles que le remplacement d'ID d'objet pour les objets references passe en parametre). Le FirstRecord methode dans notre classe sera effectivement charge de lancer l'execution de la requete (ou l'appel d'une procedure stockee) c'est une bonne pratique car elle maintient le constructeur d'une classe leger. Le Listing 2 presente les constructeurs correspondants pour la CustomerDM (gestion des donnees) de l'objet.
Hierarchies de responsabilite

je doit enfin passer de commentaire sur la hierarchie de classes impliquees dans la gestion des donnees secondaires. Notre base de TDMObject doivent etre conserves base de donnees independante, mais il doit fournir une interface que le probleme de domaine de classes peuvent utiliser. Ceci est realise en fournissant un certain nombre de methodes abstraites de la classe. La base de donnees reelle dependances sont introduits dans des descendants de TDMObject (comme TSQLServerDMObject, ou TOracleDMObject) qui mettent en œuvre les methodes abstraites, pour fournir les services necessaires a l'appui de la base de donnees access a l'encontre de leur plate-forme cible, et peut fournir d'autres methodes abstraites qui doivent etre mises en œuvre par les descendants.
Ces bases de donnees descendants sont parfaitement en droit d'introduire des dependances sur toutes les autres classes, ils ont besoin de communiquer avec leur base de donnees a l'aide des API. En general, ils fournissent une quantite raisonnable de la fonctionnalite de l'appui des questions telles que l'etablissement d'une connexion au moteur, la selection d'une base de donnees specifique, vous connecter comme utilisateur nomme et ainsi de suite. La façon dont ils atteindre de tels besoins est entierement sous leur propre controle: n'oubliez pas que notre base TDMObject interface est un contrat purement pour les services requis par le TPDObject et TPDList, et ne dicte pas de details comme un contexte de base de donnees. Cela signifie egalement que notre base de donnees d'objets specifiques peuvent tirer parti de toutes les caracteristiques de la base de donnees ou API pour maximiser la facilite d'utilisation ou de la performance, tout en se reposant tout en sachant qu'un passage a une autre base de donnees est toujours possible sans de gros changements dans le corps principal de l'application du code. En fait, comme ces classes sont independantes des applications, il est possible pour un expert base de donnees a integrer eventuellement des niveaux eleves de complexite (pour extraire le maximum de performance a partir de l'API), tout en exposant une interface simple pour les applications specifiques des utilisateurs de ces classes.
l'Un des effets secondaires de cette hierarchie, c'est que notre application de gestion des donnees des objets sera fortement liee a la fonctionnalite requise d'une base de donnees specifique de la couche, et par consequent un changement de base de donnees requiert une re-implementation de la gestion des donnees des objets. Cet impact peut etre reduit ou peut-etre meme completement supprimee si la base de donnees des classes specifiques sont conçus avec les memes services de l'experience suggere que, meme si cette approche est pratique pour les memes API de base de donnees, en fournissant une base de donnees entierement independant de la hierarchie de classe limite les possibilites de tirer parti d'une plate-forme specifique. Bien entendu, il est parfaitement possible d'introduire des sous-hierarchies a l'identique les interfaces, les plus courants etant un ensemble d'objets de base de donnees qui utilisent SQL comme leur principal moyen de communication. Cela se prete a des hierarchies telles que les suivantes, ou les trois premieres categories se trouvent a l'interieur du cadre (et inclure la majeure partie du code), et les deux dernieres classes sont specifiques a l'application:
TDMObject & #8594 TSQL_DMObject & #8594 TOracleDMObject & #8594 TMyAppDMObject & #8594 TCustomerDM
Dernier article de la question
j'ai demande comment nous pouvons utiliser notre nouvelle liste des classes pour representer les relations d'objet tel que 1-de nombreuses. Un exemple classique d'une telle relation Client.Les commandes, representant l'ensemble des commandes deja passees par un client. Comme avec nos autres 1-1 et beaucoup d'-1 relations, de les exposer a la propriete des classes est une agreable et moyen naturel de le faire. La premiere question est, comment peuvent-ils etre mis en œuvre? La reponse a cela est tres simple, nous allons utiliser la norme paresseux techniques de construction sur notre propriete la fonction d'acces a seulement creer la liste de la premiere fois qu'il est necessaire. La liste reelle de etre construits seront la liste appropriee en fonction de la relation que nous formulons, dans ce cas, nous voulons construire la liste des Commandes d'un Client connu. Le Listing 3 montre une mise en œuvre complete d'une telle relation. Le plus revelateur caracteristique est l'utilisation de 'Auto' pour construire une liste de Commandes pour un Client specifique de l'instance.
La deuxieme partie de la question etait: peut-on gerer ces operations de maniere generique, comme nous le faisons avec le plus simple des relations (rappelez-vous, nous avons implemente un generique de la methode GetObject dans notre base TPDObject classe)? Sur le visage de celui-ci, nous pourrions etre en mesure de mettre en œuvre un generique GetList methode, mais sur une inspection plus minutieuse, ce n'est pas le cas. La raison de cette incapacite a gerer les listes de façon generique, c'est que nous voulons appeler un constructeur avec parametres particuliers sur la liste necessaire. Cela necessiterait une sorte de reference a un constructeur de type, et il n'y a pas de maniere concise d'exprimer ce, tout en conservant la gestion des parametres simples. Ainsi, alors que l'on peut gerer seul les relations d'objet generique nous ne pouvons pas faire la meme pour definir les relations d'objet et ils doivent tous etre traites de façon explicite comme vu dans le Listing 1. Comme on le voit, la quantite de code est minime et ce n'est donc pas trop lourd tache.
((( Listing 1 - Personnalise constructeurs pour TCustomerList)))
constructeur TCustomerList.CreateAll
begin
& nbsp & nbsp herite de Creer (TCustomerDM.CreateAll)
fin
constructeur TCustomerList.CreateByName (const Nom: String)
begin
& nbsp & nbsp herite de Creer (TCustomerDM.CreateByName (Nom))
fin
constructeur TCustomerList.CreateByStockOrder (Item: TStockItem)
begin
& nbsp & nbsp herite de Creer (TCustomerDM.CreateByStockOrder (Item))
fin
((( Fin Listing 1 )))
((( Listing 2 - Correspondance des constructeurs pour le Client de Gestion de Donnees objet)))
constructeur TCustomerDM.CreateAll
begin
& nbsp & nbsp herite de Creer
& nbsp & nbsp Requete := 'SELECT * from Client ORDER BY Nom'
fin
constructeur TCustomerDM.CreateByName (const Nom: String)
begin
& nbsp & nbsp herite de Creer
& nbsp & nbsp Requete := 'SELECT * from Client where Nom LIKE '' Nom '%'
fin
constructeur TCustomerDM.CreateByStockOrder (Item: TStockItem)
begin
& nbsp & nbsp herite de Creer
& nbsp & nbsp Requete := 'SELECT * from Client where ItemID=' IDToStr (Item.ID)
fin
((( Fin de Liste 2 )))
& nbsp ((( Listing 3 - mise en Œuvre 1-nombre de relations )))
type
& nbsp & nbsp TCustomer = classe (TPDObject)
& nbsp & nbsp prive
& ! & ! & ! & nbsp FOrders: TOrderList
& ! & ! & ! & nbsp fonction GetOrders: TOrderList
& nbsp & nbsp public
& ! & ! & ! & nbsp destructeur de Detruire remplacer
& ! & ! & ! & nbsp propriete Commandes: TOrderList lire GetOrders
& nbsp & nbsp fin
destructeur TCustomer.Detruire
begin
& nbsp & nbsp FOrders.Gratuit
& nbsp & nbsp herite
fin
fonction de TCustomer.GetOrders: TOrderList
begin
& nbsp & nbsp si FOrders = nil alors FOrders := TOrderList.CreateByCustomer (Auto)
& nbsp & nbsp Resultat := FOrders
fin
((( Fin Listing 3 )))


La mise en œuvre des ensembles d'objets

La mise en œuvre des ensembles d'objets : Plusieurs milliers de conseils pour vous faciliter la vie.
Recommander aux amis
  • gplus
  • pinterest

Messages récents

Commentaire

Laisser un commentaire

évaluation