image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Pont (bridge) et mandataire (proxy)

Présentation

Exemple : un point en 2D

Nous souhaitons implanter un point à deux dimensions modifiable. Nous crééons son interface et son implantation :

public interface Point
{
	public void set(int x, int y);
	
	public int getX();
	
	public int getY();
}

public class ConcretePoint implements Point
{
	private int x = 0;
	private int y = 0;
	
	public void set(int x, int y)
	{
		this.x = x;
		this.y = y;
	}
	
	public int getX() { return x; }
	public int getY() { return y; }
}

On pourra bien sûr par la suite mettre en oeuvre d'autres types point héritant de l'interface (des points colorés,...).

Cas du mandataire (proxy)

Composite

Présentation

Exemple : des expressions arithmétiques

La première étape consiste à créer l'interface commune :

public interface Expression
{
	/** Returns the expression as a string with the operators at a suffix position */
	public String getExpressionString();
}

On implante maintenant une expression noeud interne (une opération binaire) avec un opérateur binaire et deux enfants :

public class BinaryOperation implements Expression
{
	public char operator;
	public Expression operand1;
	public Expression operand2;
	
	public BinaryOperation(char operator, Expression operand1, Expression operand2)
	{
		this.operator = operator;
		this.operand1 = operand1;
		this.operand2 = operand2;
	}
	
	public String getExpressionString()
	{
		return String.format("(%s) %c (%s)", operand1.getExpressionString(), operator, operand2.getExpressionString());
	}
}

Et maintenant nous implantons une expression feuille représentant un entier :

public class IntegerExpression implements Expression
{
	public int value;
	
	public IntegerExpression(int value)
	{
		this.value = value;
	}
	
	public String getExpressionString()
	{
		return "" + value;
	}
}

Mais comment pourrait-on faire si l'on souhaitait disposer également de méthodes traduisant les expressions en utilisant d'autres ordre d'affichage (préfixe, suffixe) ?

  1. Solution la plus simple : créer de nouvelles méthodes pour l'interface
  2. Solution plus propre : utiliser plusieurs objets utilisant le pattern visiteur

Interpréteur (interpreter)

Itérateur (iterator)

Façade

Présentation

Exemple : envoi d'une photo chiffrée par email

On souhaite écrire une API permettant d'envoyée une photo chiffrée par email, on va pour cela utiliser des APIs que l'on supposera déjà existantes :

  1. Tout d'abord, nous convertirons la photo de type Picture en type EmailMessage pouvant être envoyé par courrier électronique
  2. Il faut ensuite chiffrer le message pour le correspondant en utilisant une API de cryptographie
  3. Et finalement nous utilisons une API permettant d'envoyer le message en utilisant un serveur SMTP
public interface CryptedPictureSender
{
	/** Crypt and send a picture to a given recipient */
	public void send(Picture p, String recipient);
}

/** We use the Builder pattern to create an instance implementing CryptedPictureSender */
public class CryptedPictureSenderBuilder
{
	private String smtpServer;
	
	public setSMTPServer(String smtpServer)
	{
		this.smtpServer = smtpServer;
	}
	
	public CryptedPictureSender build()
	{
		return new ConcreteCryptedPictureSender(smtpServer);
	}
}

public class ConcreteCryptedPictureSender
{
	private String smtpServer;
	
	public ConcreteCryptedPictureSender(String smtpServer)
	{
		this.stmpServer = smtpServer;
	}
	
	public void send(Picture p, String recipient)
	{
		EmailMessage message = EmailMessageConverter.getInstance().convert(p); // use a singleron pattern
		EmailMessage cryptedMessage = EmailMessageCrypter.getInstance().crypt(message, recipient);
		// Now we send the message
		SMTPConnection smtp = new SMTPConnection(smtpServer);
		try {
			smtp.connect();
			smtp.send(cryptedMessage.getBytes(), recipient);
		} finally
		{
			smtp.close();
		}
	}
}

Enveloppeur (wrapper)

Présentation

Exemple : des animaux gourmands

public class HungryAnimal implements Eater
{
	private Animal animal; // the wrapped animal
	
	public HungryAnimal(Animal animal)
	{
		this.animal = animal;
	}
	
	public void eat(FoodStore fs)
	{
		// the animal eat twice because he is hungry!
		animal.eat(fs);
		animal.eat(fs);
	}
}