Ceci est une ancienne révision du document !
Table des matières
Design Pattern
Patrons de conception pour la programmation informatique.
Documentation
Commencer par lire:
Sources :
- Martin Fowler's Patterns of Enterprise Application Architecture (P of EAA) catalog
- Core J2EE Patterns sur java.sun.com.
best-practice-software-engineering's Patterns map
http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns.html
- Fundamental Design Patterns are general concepts, they are needed in most other patterns to accomplish their task.
- Interface
- Container
- Delegation
- Architectural Patterns express a fundamental structural organization or schema for software systems. They provide a set of predefined subsystems, specify their responsibilities, and include rules and guidelines for organizing the relationships between them.
- Model View Controller (MVC)
- Dependency Injection
- Structural Design Patterns are concerned with how classes and objects are composed together to form larger structures. [GoF, “Design Patterns”, Addison Wesley, ISBN 0201633612]
- Facade
- Decorator
- Proxy
- Data Access Object
- Transfer Object
- Creational Design Patterns abstract the instantiation process. They help make a system independent of how its objects are created, composed, and represented. [GoF, “Design Patterns”, Addison Wesley, ISBN 0201633612]
- Factory Method
- Abstract Factory
- Objectpool
- Singleton
- Behavioral Design Patterns are concerned with algorithms and the assignment of responsibilities between objects. [GoF, “Design Patterns”, Addison Wesley, ISBN 0201633612]
- Iterator
- Observer
- Event Listener
- Strategy
The diagram below shows the relationships between the patterns described in this documentation, the notation is according to Zimmer's classifications and relationships. [Zimmer, Walter (1995), “Relationships between Design Patterns”, from “Pattern Languages of Program Design”, Addison-Wesley.] There are three types of relationships in this diagram: uses (pattern us used by), combine (pattern can be used by), and similar (patterns are similar in their design).
Core J2EE Patterns
Data Source Architectural Patterns
Table Data Gateway
Row Data Gateway
Active Record
Active Record est une approche pour lire les données d'une base de données. Les attributs d'une table ou d'une vue sont encapsulés dans une classe. Ainsi l'objet, instance de la classe, est lié à un tuple de la base. Après l'instanciation d'un objet, un nouveau tuple est ajouté à la base au moment de l'enregistrement. Chaque objet récupère ses données depuis la base; quand un objet est mis à jour, le tuple auquel il est lié l'est aussi. La classe implémente des accesseurs pour chaque attribut.
An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
An object carries both data and behavior. Much of this data is persistent and needs to be stored in a database. Active Record uses the most obvious approach, putting data access logic in the domain object. This way all people know how to read and write their data to and from the database.
Voir:
Data Mapper
Presentation Patterns
Model View Controller
Le Modèle-Vue-Contrôleur est une architecture et une méthode (patron) de conception qui organise l'interface homme-machine (IHM) d'une application logicielle. Ce paradigme divise l'IHM en un modèle (modèle de données), une vue (présentation, interface utilisateur) et un contrôleur (logique de contrôle, gestion des événements, synchronisation), chacun ayant un rôle précis dans l'interface. Cette méthode a été mise au point en 1979 par Trygve Reenskaug, qui travaillait alors sur Smalltalk dans les laboratoires de recherche Xerox PARC.
Splits user interface interaction into three distinct roles.
Voir:
Page Controller
An object that handles a request for a specific page or action on a Web site.
Voir:
Front Controller
A controller that handles all requests for a Web site.
In a complex Web site there are many similar things you need to do when handling a request. These things include security, internationalization, and providing particular views for certain users. If the input controller behavior is scattered across multiple objects, much of this behavior can end up duplicated. Also, it's difficult to change behavior at runtime.
The Front Controller consolidates all request handling by channeling requests through a single handler object. This object can carry out common behavior, which can be modified at runtime with decorators. The handler then dispatches to command objects for behavior particular to a request.
Voir:
Template View
Renders information into HTML by embedding markers in an HTML page.
Writing a program that spits out HTML is often more difficult than you might imagine. Although programming languages are better at creating text than they used to be (some of us remember character handling in Fortran and stan-dard Pascal), creating and concatenating string constructs is still painful. If there isn't much to do, it isn't too bad, but a whole HTML page is a lot of text manipulation.
With static HTML pages - those that don't change from request to request - you can use nice WYSIWG editors. Even those of us who like raw text editors find it easier to just type in the text and tags rather than fiddle with string con-catenation in a programming language.
Of course the issue is with dynamic Web pages - those that take the results of something like database queries and embed them into the HTML. The page looks different with each result, and as a result regular HTML editors aren't up to the job.
The best way to work is to compose the dynamic Web page as you do a static page but put in markers that can be resolved into calls to gather dynamic information. Since the static part of the page acts as a template for the particular response, I call this a Template View.
Voir:
Composite View
Sophisticated Web pages present content from numerous data sources, using multiple subviews that comprise a single display page. Additionally, a variety of individuals with different skill sets contribute to the development and maintenance of these Web pages.
The Composite View pattern deals with a view made of one or more atomic, application views.
Voir:
Transform View
Two-Step View
Turns domain data into HTML in two stages: first by forming some kind of logical page, then rendering the logical page into HTML.
Two Step View (or Two-Stage View) is usually associated with the Transform View pattern; the basic idea is that your application view creates a representation that is then injected into the master view for final transformation.
If you have a Web application with many pages, you often want a consistent look and organization to the site. If every page looks different, you end up with a site that users find confusing. You may also want to make global changes to the appearance of the site easily, but common approaches using Template View (350) or Transform View (361) make this difficult because presentation decisions are often duplicated across multiple pages or transform modules. A global change can force you to change several files.
Two Step View deals with this problem by splitting the transformation into two stages. The first transforms the model data into a logical presentation without any specific formatting; the second converts that logical presentation with the actual formatting needed. This way you can make a global change by altering the second stage, or you can support multiple output looks and feels with one second stage each.
Voir:
Application Controller
Model View Presenter
Model-view-presenter (MVP) is a user interface design pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic.
- The model is an interface defining the data to be displayed or otherwise acted upon in the user interface.
- The view is an interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
- The presenter acts upon the model and the view. It retrieves data from repositories (the model), persists it, and formats it for display in the view.
Normally, the view implementation instantiates the concrete presenter object, providing a reference to itself.
At one extreme, the view is entirely passive, forwarding all interaction operations to the presenter. In this formulation, when a user triggers an event method of the view, it does nothing but invoke a method of the presenter which has no parameters and no return value. The presenter then retrieves data from the view through methods defined by the view interface. Finally, the presenter then operates on the model and updates the view with the results of the operation.
Other versions of model-view-presenter allow some latitude with respect to which class handles a particular interaction, event, or command. This is often more suitable for web-based architectures, where the view, which executes on a client's browser, may be the best place to handle a particular interaction or command.
From a layering point of view, the presenter class might be considered as belonging to the application layer in a multilayered architecture system with common layers but it can also be seen as a presenter layer of its own between the application layer and the user interface layer.
Distribution Patterns
Remote Facade
Data Transfer Object
L'un des premiers gourous à avoir introduit le Design Pattern DTO (ou Value Object) est Martin Fowler. Ces derniers temps, avec l'essor des outils de mapping o/r il devient de plus en plus aisé de transférer un modèle objet “pur” sur la couche cliente. Et la distribution de la couche de service, autre argument en faveur des DTO, est de moins en moins privilégiée dans les architectures n-tiers modernes.
- LocalDTO: dans cet article, Martin Fowler répond donc à Jon Tirsen qui titrait sur son blog “Data Transfer Objects makes me sick!
Offline Concurrency Patterns
Optimistic Offline Lock
Pessimistic Offline Lock
Coarse Grained Lock
Implicit Lock
Session State Patterns
Client Session State
Server Session State
Database Session State
Base Patterns
Factory / Fabrique
Le but de cette méthode est de déléguer certains traitements à d’autres classes, en instanciant les objets correspondants selon le contexte, ce qui permet d’avoir du code beaucoup plus maintenable, évolutif et réutilisable dans le cadre de projets assez volumineux.
Abstract Factory ou Kit
Abstract Factory ou Kit (Fabrique abstraite)
- Fournir une interface pour créer des objets d'une même famille sans préciser leurs classes concrètes.
- Le système utilise des objets qui sont regroupés en famille. Selon certains critères, le système utilise les objets d'une famille ou d'une autre. Le système doit utiliser ensemble les objets d'une famille.
- Cela peut être le cas des éléments graphiques d'un look and feel : pour un look and feel donné, tous les graphiques créés doivent être de la même famille.
- La partie cliente manipulera les interfaces des objets ; ainsi il y aura une indépendance par rapport aux classes concrètes. Chaque fabrique concrète permet d'instancier une famille d'objets (éléments graphiques du même look and feel) ; ainsi la notion de famille d'objets est renforcée.
Factory Method ou Virtual Constructor (Fabrique)
- Définir une interface pour la création d'un objet, mais laisser les sous-classes décider quelle classe instancier.
- Déléguer l'instanciation aux sous-classes.
- Dans le fonctionnement d'une classe, il est nécessaire de créer une instance. Mais, au niveau de cette classe, on ne connaît pas la classe exacte à instancier.
- Cela peut être le cas d'une classe réalisant une sauvegarde dans un flux sortant, mais ne sachant pas s'il s'agit d'un fichier ou d'une sortie sur le réseau.
- La classe possède une méthode qui retourne une instance (interface commune au fichier ou à la sortie sur le réseau). Les autres méthodes de la classe peuvent effectuer les opérations souhaitées sur l'instance (écriture, fermeture). Les sous-classes déterminent la classe de l'instance créée (fichier, sortie sur le réseau). Une variante du Pattern existe : la méthode de création choisit la classe de l'instance à créer en fonction de paramètres en entrée de la méthode ou selon des variables de contexte.
Strategy
Le design pattern Strategy définit une famille d’algorithmes encapsulés et interchangeables. Strategy laisse l’algorithme varier indépendamment du client qui l’utilise. C’est une solution à envisager lorsqu’un problème peut être résolu par différents algorithmes. Cas d’utilisation :
- plusieurs classes différant seulement dans leur comportement
- besoin de plusieurs variantes d’un algorithme
- un algorithme utilise des données que le client ne devrait pas connaître
- une classe définit plusieurs comportements lesquels nécessitant de nombreux tests conditionnels
Observer
Le patron de conception observateur/observable est utilisé en programmation pour envoyer un signal à des modules qui jouent le rôle d'observateur. En cas de notification, les observateurs effectuent alors l'action adéquate en fonction des informations qui parviennent depuis les modules qu'ils observent (les “observables”).
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
Q: can't understand how to use on a website ?!
I understand the Observer pattern, but I don't know how it can be used on a website. It can be an helper that return a constant, but an observer is realy strange.R: It has it's uses
It's useful as a plugin system, for extensible apps.
Voir:
Composite
Catégorie: structurel.
Un objet composite est constitué d'un ou de plusieurs objets similaires (ayant des fonctionnalités similaires). L'idée est de manipuler un groupe d'objets de la même façon que s'il s'agissait d'un seul objet. Les objets ainsi regroupés doivent posséder des opérations communes, c'est-à-dire un “dénominateur commun”.
Quand l'utiliser ?
Vous avez l'impression d'utiliser de multiples objets de la même façon, souvent avec des lignes de code identiques ou presque. Par exemple, lorsque la seule et unique différence entre deux méthodes est que l'une manipule un objet de type Carré, et l'autre un objet Cercle. Lorsque, pour le traitement considéré, la différenciation n'a pas besoin d'exister, il serait plus simple de considérer l'ensemble de ces objets comme homogène.
Voir:
Facade
Façade
A single class that represents an entire subsystem.
Vous ne vous êtes jamais penché sur le problème de savoir comment votre banquier traitait vos chèques ? Vous fournissez au guichet le bordereau dûment rempli comme le prévoit la façade et ce qu'il se passe après vos importe peu, du moment que votre argent va sur votre compte.
C'est donc une pratique courante qui, étrangement, se perd lorsqu'on développe des logiciels. Bien souvent, on fait ce qu'il y a à faire sans trop se demander s'il ne serait pas opportun d'isoler un sous ensemble derrière une API. En programmation à objet on encapsule ainsi des éléments. Mais on pense rarement que tout un ensemble pourrait être caché par une seule classe. La littérature sur ce sujet est pourtant vaste. Et utiliser une façade à bon escient est un gage pour l'avenir.
Si vous arrivés à bien cloisonner vos sous-ensembles, alors en changer une partie n'impliquera que des changements mineurs sur le reste, tant que l'interface ne change pas.
L'intention du modèle Façade est de fournir une interface unifiée à l'ensemble des interfaces d'un sous-système. La Facade fournit une interface de plus haut-niveau, qui rend le sous-système plus facile à utiliser.
Note sur le mot Interface dans cette définition :
- Limite entre deux systèmes,
- Frontière permettant l'échange entre deux systèmes.
Le mot clé Interface dans les langages objet comme Java et C# signifie aussi une limite, mais porte plus le sens de “Contrat d'utilisation”. Cette note pour dire qu'avec le modèle Façade, il n'est pas nécessaire de définir d'Interface (de Contrat).
Voir:
Interface / Adapteur
Synonymes: Encapsulateur, Empaquetage.
An interface defines the signature operations of an entity, it also sets the communication boundary between two entities, in this case two pieces of software. It generally refers to an abstraction that an asset provides of itself to the outside.
Use an interface when:
- you want to specify how classes exchange messages. I.e., every time, when a class should be reused, or used outside a specific context (package) declare the communication interface as an Interface type
- you have to switch the implementation of a module during run-time
- at design-time you don't yet know which implementation you will use at compile-time
Related Patterns:
- Many other patterns use interfaces, a lot of them depend on the interface pattern.
- It is possible to combine the interface pattern with virtually any other pattern to make them more flexible.
Pour des raisons de conformité à une norme, pour ne pas dépendre d'une implémentation, pour permettre l'évolution de votre projet, il arrive que vous ayez besoin de vous reposer sur une interface ou une API qui n'est pas précisément celle qui vous est fournie. Ce design pattern vous propose de pallier cette problématique.
Such a construction of using an interface is often combined with the Factory-Pattern to retrieve the Implementation of the interface.
Gateway
Mapper
Layer Supertype
Separated Interface
Registry
A well-known object that other objects can use to find common objects and services.
A Registry is essentially a global object, or at least it looks like one - even if it isn't as global as it may appear.
Why use the registry instead of globals?
Usage of globals is often considered an anti-pattern. Globals are difficult to test against, as you cannot predict where and when they may be overwritten. A registry can help prevent this, and also ensure that there is a single location for retrieving objects.
Souvent utilisé pour l'accès à la configuration.
Voir:
Value Object
Money
Special Case
Plugin
Separated Interface (476) is often used when application code runs in multiple runtime environments, each requiring different implementations of particular behavior. Most developers supply the correct implementation by writing a fac-tory method. Suppose you define your primary key generator with a Separated Interface (476) so that you can use a simple in-memory counter for unit testing but a database-managed sequence for production. Your factory method will most likely contain a conditional statement that looks at a local environment variable, determines if the system is in test mode, and returns the correct key generator. Once you have a few factories you have a mess on your hands. Establishing a new deployment configuration - say “execute unit tests against in-memory database without transaction control” or “execute in production mode against DB2 database with full transaction control” - requires editing conditional statements in a number of factories, rebuilding, and redeploying. Configuration shouldn't be scattered throughout your application, nor should it require a rebuild or redeployment. Plugin solves both problems by providing centralized, runtime configuration.
Voir :
Service Stub
Record Set
Dependency Injection
Le principe de base de l'injection de dépendance est que les composants se voient affecter leurs dépendances à travers leurs constructeurs, leurs méthodes ou directement via leurs propriétés. En règle générale, on utilisera les constructeurs pour les dépendances obligatoires et les setters pour les dépendances facultatives.
Nous n'avons pas besoin d'un container pour bénéficier de l'injection de dépendance, mais quand on commence à avoir beaucoup d'objets avec beaucoup de dépendances (framework, big application) un container devient une vrai valeur ajoutée.
Avec un container:
L'injection de dépendances est un mécanisme qui permet d'implanter le principe de l'Inversion de contrôle (ou inversion des dépendances). Il consiste à créer dynamiquement (injecter) les dépendances entre les différentes classes en s'appuyant généralement sur une description (fichier de configuration). Ainsi les dépendances entre composants logiciels ne sont plus exprimée dans le code de manière statique mais déterminées dynamiquement à l'exécution.
Anti-patterns:
Voir:
- Principe d'inversion des dépendances: http://www.crossbowlabs.com/dossiers/principesoo/dip
- Présentation de l'injection de dépendance par Fabien Potencier
Chain of Responsibility
Le design pattern Chain of Responsibility est souvent peu connu et pourtant il peut être très utile dans la gestion des logs et erreurs.
Généralement, la liste des choix disponibles pour le traitement des problèmes se limite à :
- générer des logs
- envoyer un e-mail à l'administrateur
- générer une exception.
Bien qu'il existe différents composants disponibles répondant unitairement à ces besoins, le développeur doit souvent mixer les solutions, comme par exemple sur détection d'un comportement utilisateur invasif et non-autorisé alors il faut avertir l'administrateur par e-mail, tracer les informations dans un log et générer une exception pour stopper le traitement.
Le design pattern “Chain of Responsibility” permet de réduire cette complexité en créer une seule entité chargée de gérer tous les niveaux d'alerte et d'affecter ceux-ci au niveau de responsabilité correspondant.
Concrètement, le design pattern “Chain of Responsibility” consiste à :
- créer une liste chaînée d'objet, chacun ayant un seuil de déclenchement et ayant des actions propres,
- déléguer la connaissance du point d'entrée de la chaîne de responsabilité à un objet façade.
Voir: