Ce document ne peut pas être employé dans le cadre d'un cours ou d'une formation sans mon accord
Je suis formateur Java, XML tout niveau : plus de renseignements.
(c) 2005 Alexandre Brillant


Bases

Catégories

Cadre

Rôle

Déléguer le processus de création d'objets à une classe

1°) Abstract Factory

Rôle

Cacher la nature des objets créés par des interfaces tout en maintenant leurs cohérences.

Java

public interface AbstractFactory {
public Engine getEngine();
public Tyre getTyre();
}

public class ConcreteFactorySNECMA implements AbstractFactory {
public Engine getEngine() {
return new EngineSNECMA();
}

public Tyre getTyre() {
return new TyreSNECMA();
}
}

2°) Method Factory

Rôle

Cacher la nature des objets créés par des interfaces et faciliter la conception par une règle.

Java

public interface HeXaneNodeFactory {
public Node getNode( String type );
}

public class ConreteHeXaneNodeFactory implements HeXaneNodeFactory {
public Node getNode( String type ) {
if ( "Component".equals( type ) )
return new ComponentNode();
else
if ( "Link".equals( type ) )
return new LinkNode();
else
return new DefaultNode();
}
}

3°) Singleton

Rôle

Cacher l'accès au constructeur et maintenir un nombre limité d'instances.

Java

public class ButtonRenderer {

private ButtonRenderer() {
...
}

// Accès au singleton
public static ButtonRenderer getButtonRenderer() {
if ( renderer == null )
renderer = new ButtonRenderer();
return renderer;
}

private static ButtonRenderer renderer;
}

4°) Builder

Rôle

Déléguer la construction d'un objet sur d'autres classes.

UML

Java

public interface RepositoryBuilder {
public void buildContent();
public RepositoryContent getContent();
}

public class ConcreteRepositoryBuilder implements RepositoryBuilder {
public void buildContent() {
files = ( new File( "." ) ).list();
}

public getContent() {
return new RepositoryContent( files );
}

String[] files;
}

Cadre

Besoin d'une structure intermédiaire de classes participant à une fonction. Utilisation de librairies indépendantes. Evolution d'une composition à l'exécution.

Ex : Puzzle, jeu de cubes.

Rôle

Associer des classes pour former des structures homogènes plus grandes accessible par une classes.

1°) Adapter

Rôle

Permettre le support d'une nouvelle interface

UML

Java

public interface Runnable() {
public void run();
}

public class Process implements Runnable() {
public void run() {
...
}
}

public interface Schedulable {
public void run( long delay );
}

public class ProcessAdapter implements Schedulable extends Process {

public void setProcess( Process process ) {
this.process = process;
}

public void run() {
process.run();
}

public void run( long delay ) {
wait( delay );
run();
}

private Process process;
}

2°) Bridge

Rôle

Pouvoir faire évoluer des classes d'abstraction (ex: une fenêtre) sans toucher au niveau implémentation (ex: une fenêtre pour window).

Ex : Swing (pas de peer comme dans AWT)

UML

Java

// Abstract class
public class Canvas {
// Set the canvas implementation for (Windows, Motif...)
public void setCanvas( CanvasPeer canvas ) {
this.canvas = canvas;
}
protected CanvasPeer canvas;

public void draw() {
canvas.draw();
}
}

// Abstraction inheritance
public class ExtendedButton extends Canvas {
public void draw() {
canvas.drawText( "push me" );
...
}
}

3°) Composite

Rôle

Pas de différentiation entre un aggrégat d'objets et un objet.

Ex : Dans un logiciel de dessin vectoriel un groupe d'objets lié est un nouvel objet.

UML

Java

public class GroupComponent extends Component {
public void addComponent( Component component ) {
...
}

public void removeComponent( Component component ) {
...
}

public void paint( Graphics gc ) {
// Paint each sub component
}
}

4°) Decorator

Rôle

Pouvoir enrichir dynamiquement la représentation graphique d'un objet.

Ex : Border swing

Java

// Decorator for any rendering
public class ExtendedRenderer extends Renderer {
public void addRenderer( Renderer renderer ) {
...
}

public void removeRenderer( Renderer renderer ) {
...
}

public void paint( Grapics gc ) {
// Paint all renderer
...
}
}

5°) Facade

Rôle

Regrouper les intéractions avec une API dans une classe ou façade.

UML

Java

// Facade for the dynamix API
public class DynamixFacade {
// Merge data and the model to produce output
public void transform( Hashtable data, String model, String output ) {
...
}
}

6°) Flyweight

Rôle

Minimiser le nombre d'instance and distinguant deux états dans un objet :

Ex : Caractères dans un traitement de texte, avec le code ASCII pour l'état personnel et la position du caractère pour l'état global.

UML

Java

public class CaracterView extends View {
public void draw() {
...
}

// Personal state
char c;
}

public void Editor {
public void initCars() {
...
// Reset carView for all caracters once
}

public void addCaracterView( char c ) {
cars.addElement( carView.get( c ) );
}

public void draw() {
// Compute the global state

// Paint using cars View
}

Hashtable carView = new Hastable();
Vector cars = new Vector();
}

7°) Proxy

Rôle

Objet supplémentaire jouant le rôle d'un autre objet. Types de proxy :

UML

Java

// Share interface client/server
public interface Action {
public void doAction();
}

// Remote action (on server)
public class ConcreteAction implements Action {
public void doAction() {
...
}
}

// Client proxy
public class ActionStub implements Action {

public void doAction() {
// Send Tcp/Ip order for calling remote doAction
}
}

Cadre

Des traitements différents se font en fonction d'un contexte.

Ex : Contrôleur Java (sur button et checkbox)

Rôle

Limiter les responsabilités des traitements à certaines classes. Contrôler les flux de traitements.

1°) Chain of responsability

Rôle

Définir une arborescence de traitement.

Ex: Une info-bulle est affichée sur certains boutons, sinon c'est l'info-bulle du conteneur qui est affiché.

UML

Java

// Decide to handle
public interface Handler {
public boolean handle( Context context );
public void handler();
}

// List of handlers
public void HandlerManager {

public void addHandler( Handler handler ) {}

public void handle() {
// search the first handler and launch it
}
}

2°) Command

Rôle

Déléguer un traitement sur une autre classe.

Ex : Contrôleur java

UML

Java

myButton.addActionListener( myControleur );

3°) Interpreter

Rôle

Offrir un mini - interpréteur syntaxique et permettre l'utilisation de commandes avec un language adapté.

Ex : Expressions régulières (^a|(b?c*)) pour a b bcccc... cccc...

L'idée est d'accocier à une grammaire une classe et de construire par des instances l'arbre de syntaxe abstrait (premier arbre produit par la compilation). Ces instances sont ensuite parcourues pour valider / exécuter la commande.

Pour des grammaires complexes les outils de conversion automatiques sont indispensables (équivallent lex/yacc javacc).

UML

Java

lettre ::= 'a', 'b', 'c'
lettres ::= {} | lettre lettres
expression ::= '(' expression ')' | lettres

// Letter rule
public class Letter implements Interpretable {
public void interpret( Context context ) throws Exception {
char c = context.nextInput();
if ( c == 'a' | c == 'b' | c == 'c' )
letter = c;
else
throws Exception( "Invalid input :" + c );
}
private char letter;
}

// Letters rule
public class Letters implements Interpretable {
public void interpret( Context context ) throws Exception {
for ( int i = 0; i < letters.size(); i++ ) {
( (Letter)( letters.elementAt( i ) ) ).interpret(
context );
}
}
// Add a new letters
public void addLetter( Letter letter ) {
letters.addElement( letter );
}
private Vector letters = new Vector();
}

// Expression rule
public class Expression implements Interpretable {
public void interpret( Context context ) throws Exception {
char c = context.nextInput();
if ( expression != null ) {
if ( c == '(' ) {
expression.interpret( context );
if ( context.nextInput() != ')' )
throws Exception( "Invalid parenthesis" );
}
} else
letters.interpret( context );
}

public void setLetters( Letters letters ) {
this.letters = letters;
}

public void setExpression( Expression expression ) {
expression = expression;
}

private Letters letters;
private Expression expression;
}


// Instance to interpret (ab)

Letter a = new Letter( 'a' );
Letter b = new Letter( 'b' );
Letters l = new Letters();
l.addLetter( a );
l.addLetter( b );
Expression e1 = new Expression();
e1.setLetters( l );
Expression e2 = new Expression();
e2.setExpression( e1 );

e2.interpret( new Context( "(ab)" ) );

4°) Iterator

Rôle

Pouvoir accéder au contenu séquentiel d'une collection sans connaître le système de stockage.

Ex : Enumeration sur Vector / Hashtable

UML

Java

// Client iterator
public interface Iterator {
public Object first();
public Object next();
public boolean hasMoreElements();
e
}

// Data structure with object array
public ArrayData {
public ArrayIterator( Object[] array ) {
this.array = array;
}

public Iterator getIterator() {
return new Iterator() {
public boolean hasMoreElements() {
return i < array.length;
}

public Object first() { return array[ i = 0 ]; }
public Object next() { return array[ i++ ]; }
int i;
};
}

private Object[] array;
}

5°) Mediator

Rôle

Lorsque trop d'intéraction existent entre objets, les stocker dans un contrôleur spécifique.

Ex : Une liste avec un champ texte. Lorsque un caractère est entré dans le champ texte, la liste se met à jour, lorsque une sélection est faite dans la liste, le champ texte se met à jour.

UML

Java

// Interaction between two buttons
public class Mediator implements ActionListener {
public void setButton1( Button button1 ) {
this.button1 = button1;
button1.addActionListener( this );
}

public void setButton2( Button button2 ) {
this.button2 = button2;
button2.addActionListener( this );
}

public void actionPerformed( ActionEvent evt ) {
if ( evt.getSource() == button1 ) {
button2.setText( button1.getText() );
} else
button1.setText( button2.getText() );
}

private Button button1, button2;
}

6°) Memento

Rôle

Pouvoir stocker/restaurer l'état d'un objet.

Ex : Swing avec sérialization XML (transformation swing->xml / xml->swing).

UML

Java

public class BooleanState {
public BooleanState( boolean state ) {
this.state = state;
}

public boolean isActive() {
return state;
}

boolean state;
}

public class Boolean {
public void setState( BooleanState state ) {
value = state.isActive;
}

public void getState() {
return new BooleanState( state );
}

boolean value;
}

7°) Observer

Rôle

Informer un objet d'un changement dans un autre sans créer de liaison explicite.

Ex : Une feuille excel est mise à jour, différents graphes se rafraîchissent.

UML

Java

// Observable button that notify observer for click
public class ButtonObservable {

public ButtonObservable() {
super();
addActionListener( this );
}

public void addObserver( Observer observer ) {
observable.addObserver( observer );
}

public void actionPerformed( ActionEvent evt ) {
observable.notifyObservers();
}

Observable observable = new Observable();
}

8°) State

Rôle

Obtenir des traitements en fonction de l'état courant.

UML

Java

public interface TCPState {
public void open();
public void close();
public void listen();
}

public interface TCPOpen extends TCPState {
}

public interface TCPListen extends TCPState {
}

public interface TCPClose extends TCPState {
}

public class TCPHandler {

public void open() {
state.open();
}

public void close() {
state.close();
}

public void listen() {
state.listen();
}

public void setState( TCPState state ) {
this.state = state;
}

public TCPState state;
}

9°) Strategy

Rôle

Plus vaste que le pattern "state", permet de choisir un algorithme adapté au contexte.

UML

Java

public class IndentDocument {
public void setIndenter( Indenter indenter );

// Depend on the context
public void indent( Document doc ) {
indenter.indent( doc );
}
}

// Indent document strategy
public interface Indenter {
public void indent( Document doc );
}

10°) Template method

Rôle

Définir le squelette d'un algorithme et déléguer certaines actions aux sous-classes.

Ex : Trier une liste d'objet. L'algorithme de tri délègue la comparaison des objets.

UML

Java

public abstract class Sorter {

// Template method
public void sort( Object[] data ) {
for ( int i = 0; i < data.length; i++ ) {
int min = i;
for ( int j = 1; j < data.length; j++ ) {
if ( isSmallerThan( data[ min ], data[ j ] ) )
min = j;
}
Object tmp = data[ i ];
data[ i ] = data[ min ];
data[ min ] = tmp;
}
}

public abstract boolean isSmallerThan( Object data1, Object data2 );
}

11°) Visitor

Rôle

Lors du parcours d'une structure, pouvoir concentrer les actions hors de l'élément de la structure.

UML

Java

public interface Visitor {
public void actionForAllNode( Node node );
public void actionForCustomNode( CustomNode node );
}

public class Node {
public void accept( Visitor visitor ) {
visitor.actionForAllNode( this );
}
}

public class CustomNode extends Node {
public void accept( Visitor visitor ) {
visitor.actionForCustomNode( this );
}
}

Le design pattern oblige le développeur à segmenter son programme en fonctionnalités qu'il peut ensuite faire évoluer sans modifier l'architecture globale de l'application.