Le chapitre passe en revue sept problèmes qui doivent être résolus afin de concevoir correctement Lexi, y compris les contraintes qui doivent être suivies. Chaque problème est analysé en profondeur, et des solutions sont proposées., Chaque solution est expliquée en intégralité, y compris le pseudo-code et une version légèrement modifiée de la technique de modélisation D’objet le cas échéant.
enfin, chaque solution est directement associée à un ou plusieurs modèles de conception. Il est montré comment la solution est une implémentation directe de ce modèle de conception.
Les sept problèmes (y compris leurs contraintes) et leurs solutions (y compris le ou les motifs référencés), sont les suivants:
document StructureEdit
le document est « un arrangement d’éléments graphiques de base » tels que des caractères, des lignes, d’autres formes, etc.,, qui « capturent le contenu d’information total du document » (p. 35). La structure du document contient une collection de ces éléments, et chaque élément peut à son tour être une sous-structure d’autres éléments.
problèmes et contraintes
- Le texte et les graphiques doivent être traités de la même manière (c’est-à-dire que les graphiques ne sont pas une instance dérivée de text, ni vice versa)
- L’implémentation doit traiter les structures complexes et simples de la même manière. Il ne devrait pas avoir à connaître la différence entre les deux.,
- Les dérivés spécifiques des éléments abstraits devraient avoir des éléments analytiques spécialisés.
Solution et Modèle
une composition récursive est une structure hiérarchique d’éléments, qui construit « des éléments de plus en plus complexes à partir d’éléments plus simples » (pp. 36). Chaque nœud de la structure connaît ses propres enfants et son parent. Si une opération doit être effectuée sur l’ensemble de la structure, chaque nœud appelle l’opération sur ses enfants (récursivement).
ceci est une implémentation du modèle composite, qui est une collection de nœuds., Le nœud est une classe de base abstraite, et les dérivés peuvent être soit des feuilles (singulier), soit des collections d’autres nœuds (qui à leur tour peuvent contenir des feuilles ou des nœuds de collection). Lorsqu’une opération est effectuée sur le parent, cette opération est récursivement transmise dans la hiérarchie.
FormattingEdit
Le formatage diffère de la structure. Le formatage est une méthode de construction d’une instance particulière de la structure physique. Cela comprend le découpage du texte en lignes, l’utilisation de traits d’Union, l’ajustement des largeurs de marge, etc.,
problèmes et contraintes
- équilibre entre la qualité (formatage), la vitesse et l’espace de stockage
- gardez le formatage indépendant (découplé) de la structure du document.
Solution et motif
Une Classe Compositor encapsulera l’algorithme utilisé pour formater une composition. Compositeur est une sous-classe de l’objet primitif de la structure du document. Un compositeur a une instance associée à un objet Composition., Lorsqu’un compositeur exécute son Compose()
, il parcourt chaque élément de sa Composition associée et réarrange la structure en insérant des objets ligne et Colonne au besoin.
Le Compositor lui-même est une classe abstraite, permettant aux classes dérivées d’utiliser différents algorithmes de formatage (tels que le double espacement, les marges plus larges, etc.)
Le Modèle de Stratégie est utilisé pour atteindre cet objectif. Une stratégie est une méthode d’encapsulation de plusieurs algorithmes à utiliser en fonction d’un contexte changeant., Dans ce cas, le formatage doit être différent, selon que le texte, les graphiques, les éléments simples, etc. sont en cours de formatage.
embellissement de l’interface utilisateur Edit
possibilité de modifier l’interface graphique utilisée par l’utilisateur pour interagir avec le document.,
problèmes et contraintes
- délimiter une page de texte avec une bordure autour de la zone d’édition
- barres de défilement qui permettent à l’utilisateur d’afficher différentes parties de la page
- Les objets de l’interface utilisateur ne doivent pas connaître les embellissements
- éviter une « explosion de classes » qui serait causée par une sous-classification pour « toutes les combinaisons possibles d’embellissements » et d’éléments (p. 44)
Solution et Modèle
l’utilisation d’une enceinte transparente permet d’ajouter à une composition des éléments qui augmentent le comportement de la composition. , Ces éléments, tels que Border et Scroller, sont des sous-classes spéciales de l’élément singulier lui-même. Cela permet d’augmenter la composition, en ajoutant efficacement des éléments de type État. Étant donné que ces augmentations font partie de la structure, leur Operation()
approprié sera appelé lorsque le Operation()
de la structure est appelé. Cela signifie que le client n’a pas besoin de connaissances particulières ou d’interface avec la structure pour utiliser les embellissements.,
il s’agit d’un motif de décorateur, qui ajoute des responsabilités à un objet sans modifier l’objet lui-même.
prise en charge de plusieurs normes D’aspect et de convivialité.
L’aspect et la convivialité font référence aux normes D’interface utilisateur spécifiques à la plate-forme. Ces normes « définissent des lignes directrices sur la façon dont les applications apparaissent et réagissent à l’utilisateur » (p. 47).
problèmes et contraintes
- l’éditeur doit implémenter des normes de plusieurs plates-formes afin qu’il soit portable
- s’adapte facilement aux normes nouvelles et émergentes
- permet un changement d’apparence au moment de l’exécution (c’est-à-dire,: Pas de codage en dur)
- avoir un ensemble de sous-classes élémentaires abstraites pour chaque catégorie d’éléments (barre de défilement, boutons, etc.)
- avoir un ensemble de sous-classes concrètes pour chaque sous-classe abstraite qui peut avoir un standard d’apparence et de convivialité différent. (ScrollBar ayant MotifScrollBar et PresentationScrollBar pour Motif et présentation look-and-feels)
Solution et motif
étant donné que la création d’objet de différents objets concrets ne peut pas être effectuée lors de l’exécution, le processus de création d’objet doit être abstrait., Cela se fait avec un guiFactory abstrait, qui prend la responsabilité de créer des éléments D’interface utilisateur. Le guifactory abstrait a des implémentations concrètes, telles que MotifFactory, qui crée des éléments concrets du type approprié (MotifScrollBar). De cette façon, le programme n’a besoin que de demander une barre de défilement et, au moment de l’exécution, il recevra l’élément concret correct.
Ceci est une usine abstraite. Une usine régulière crée des objets en béton d’un type. Une usine abstraite crée des objets concrets de différents types, en fonction de la mise en œuvre concrète de l’usine elle-même., Sa capacité à se concentrer non seulement sur des objets concrets, mais sur des familles entières d’objets concrets « le distingue des autres modèles de création, qui n’impliquent qu’un seul type d’objet produit » (pp. 51).
Supporting Multiple Window SystemsEdit
tout comme l’apparence est différente d’une plate-forme à l’autre, la méthode de gestion de windows l’est également. Chaque plate-forme affiche, présente, gère les entrées et les sorties et couche les fenêtres différemment.,
problèmes et contraintes
- l’éditeur de documents doit fonctionner sur de nombreux « systèmes de fenêtres importants et largement incompatibles » qui existent (p. 52)
- une fabrique abstraite ne peut pas être utilisée. En raison de normes différentes, il n’y aura pas de classe abstraite commune pour chaque type de widget.
- ne créez pas de nouveau système de fenêtrage non standard
Solution et Modèle
il est possible de développer « nos propres classes de produits abstraits et concrets », car « tous les systèmes de fenêtres font généralement la même chose » (p. 52)., Chaque système de fenêtre fournit des opérations pour dessiner des formes primitives, iconifier/dés-iconifier, redimensionner et actualiser le contenu de la fenêtre.
Une classe de base abstraiteWindow
peut être dérivée des différents types de fenêtres existantes, telles que application, iconified, dialog. Ces classes contiendront des opérations associées à windows, telles que le remodelage, l’actualisation graphique, etc. Chaque fenêtre contient des éléments dont les fonctionsDraw()
sont appelées par les propres fonctions liées au dessin deWindow
.,
afin d’éviter d’avoir à créer des sous-classes de fenêtres spécifiques à la plate-forme pour chaque plate-forme possible, une interface sera utilisée. La balise Window
de classe mettra en œuvre un Window
mise en œuvre (WindowImp
) classe abstraite. Cette classe sera ensuite dérivée en plusieurs implémentations spécifiques à la plate-forme, chacune avec des opérations spécifiques à la plate-forme., Ainsi, un seul ensemble de Window
classes sont nécessaires pour chaque type de Window
, et un seul ensemble de WindowImp
classes sont nécessaires pour chaque plate-forme (plutôt que le produit Cartésien de tous les types disponibles et les plates-formes). De plus, l’ajout d’un nouveau type de fenêtre ne nécessite aucune modification de l’implémentation de la plate-forme, ou vice versa.
ceci est un modèle de Pont. Window
et WindowImp
sont différents, mais connexes., Window
traite de fenêtrage dans le programme, et WindowImp
traite avec fenêtrage sur une plate-forme. L’un d’eux peut changer sans jamais avoir à modifier l’autre. Le modèle de pont permet à ces deux « hiérarchies de classes distinctes de travailler ensemble même lorsqu’elles évoluent indépendamment » (p. 54).
User OperationsEdit
toutes les actions que l’utilisateur peut effectuer avec le document, allant de la saisie de texte, de la modification de la mise en forme, de la suppression, de l’enregistrement, etc.,
problèmes et contraintes
- Les opérations doivent être accessibles via différentes entrées, telles qu’une option de menu et un raccourci clavier pour la même commande
- chaque option a une interface, qui doit être modifiable
- Les opérations sont implémentées dans plusieurs classes différentes
- afin d’éviter le couplage, il ne doit pas y avoir beaucoup de dépendances entre l’implémentation et les classes d’interface utilisateur.,
- Les commandes Undo et redo doivent être prises en charge sur la plupart des opérations de modification de documents, sans limite arbitraire sur le nombre de niveaux d’undo
- Les fonctions ne sont pas viables, car elles n’annulent pas / redo facilement, ne sont pas facilement associées à un état et sont difficiles à étendre ou à réutiliser.
- Les Menus doivent être traités comme des structures composites hiérarchiques. Par conséquent, un menu est un élément de menu qui contient les éléments de menu qui peut contenir d’autres éléments de menu, etc.,
Solution et Modèle
chaque élément de menu, plutôt que d’être instancié avec une liste de paramètres, est plutôt fait avec un objet Command.
Command est un objet abstrait qui n’a qu’une seule méthode abstraite Execute()
. Les objets dérivés étendent la méthode Execute()
de manière appropriée (c’est-à-dire que le PasteCommand.Execute()
utiliserait le tampon du presse-papiers du contenu). Ces objets peuvent être utilisés par des widgets ou des boutons aussi facilement que par des éléments de menu.,
À l’appui de défaire et refaire, Command
est également donnée Unexecute()
et Reversible()
. Dans les classes dérivées, la première contient du code qui annulera cette commande, et la seconde renvoie une valeur booléenne qui définit si la commande est annulable. Reversible()
permet à certaines commandes d’être non-annulables, comme une commande Save.
Tous lesCommands
exécutés sont conservés dans une liste avec une méthode de conservation d’un marqueur « présent » directement après la commande la plus récente exécutée., Une demande d’annulation appellera le Command.Unexecute()
directement avant » present », puis déplacera » present » en arrière d’une commande. Inversement, une requêteRedo
appelleraCommand.Execute()
après « present » et déplacera « present » vers l’avant.
cette approcheCommand
est une implémentation du modèle de commande. Il encapsule les requêtes dans des objets et utilise une interface commune pour accéder à ces requêtes. Ainsi, le client peut gérer différentes demandes et les commandes peuvent être dispersées dans l’application.,
vérification orthographique et césure
Il s’agit de la capacité de l’éditeur de document à analyser textuellement le contenu d’un document. Bien qu’il existe de nombreuses analyses qui peuvent être effectuées, la vérification orthographique et la mise en forme de césure sont au centre.
problèmes et contraintes
- permettre plusieurs façons de vérifier l’orthographe et d’identifier les lieux de césure
- permettre une expansion pour une analyse future (par exemple, le nombre de mots, la vérification de la grammaire)
- être capable d’itérer à travers le contenu d’un texte sans accéder à la structure,, tableau, liste chaînée, chaîne)
- permet toute manière de traverser le document (du début à la fin, de la fin au début, par ordre alphabétique, etc.)
Solution et Modèle
la suppression de l’index basé sur des entiers de l’élément de base permet d’implémenter une interface d’itération différente. Cela nécessitera des méthodes supplémentaires pour la traversée et la récupération d’objets. Ces méthodes sont mises dans une interface abstraite Iterator
., Chaque élément implémente ensuite une dérivation du Iterator
, en fonction de la façon dont cet élément conserve sa liste (ArrayIterator
, LinkListIterator
, etc.).
Les fonctions de traversée et de récupération sont placées dans l’interface de l’itérateur abstrait. Les futurs itérateurs peuvent être dérivés en fonction du type de liste qu’ils parcourront, tels que des tableaux ou des listes liées. Ainsi, quel que soit le type de méthode d’indexation utilisé par toute implémentation de l’élément, il aura l’itérateur approprié.
ceci est une implémentation du modèle itérateur., Il permet au client de parcourir n’importe quelle collection d’objets, sans avoir besoin d’accéder directement au contenu de la collection, ni de se préoccuper du type de liste utilisée par la structure de la collection.
Maintenant que la traversée a été traitée, il est possible d’analyser les éléments d’une structure. Il n’est pas possible de construire chaque type d’analyse dans la structure des éléments eux-mêmes; chaque élément devrait être codé, et une grande partie du code serait le même pour des éléments similaires.
Au Lieu de cela, une méthode génériqueCheckMe()
est intégrée dans la classe abstraite de l’élément., Chaque Itérateur est donné une référence à un algorithme spécifique (comme la vérification orthographique, grammaticale, etc.). Lorsque cet itérateur parcourt sa collection, il appelle le CheckMe
de chaque élément, en passant l’algorithme spécifié. CheckMe
transmet ensuite une référence à son élément à cet algorithme pour analyse.
Ainsi, pour effectuer une vérification orthographique, un avant la fin de l’itérateur serait donnée une référence à un SpellCheck
objet., L’itérateur accéderait ensuite à chaque élément en exécutant sa méthodeCheckMe()
avec le paramètreSpellCheck
. Chaque CheckMe
appellerait alors le SpellCheck
, en passant une référence à l’élément approprié.
de cette manière, n’importe quel algorithme peut être utilisé avec n’importe quelle méthode de traversée, sans couplage de code en dur l’un avec l’autre. Par exemple, Trouver peut être utilisé comme « rechercher le suivant » ou « précédent », selon si un « avant » itérateur a été utilisé, ou un « à l’envers » itérateur.,
de plus, les algorithmes eux-mêmes peuvent être responsables de traiter différents éléments. Par exemple, un algorithme SpellCheck
ignorerait un élément Graphic
, plutôt que d’avoir à programmer chaque élément dérivé Graphic
pour ne pas s’Envoyer à un élément SpellCheck
.