samedi 17 janvier 2015

Java / Design Pattern Stratégie

Le pattern stratégie est utile pour des situations où il est nécessaire de choisir dynamiquement un algorithme à exécuter.

Vous mettez en place une stratégie dans l'exécution de votre code selon le contexte.

Par exemple : vous souhaitez gérer la première exécution d'une application nouvellement installée.

Lors de la première exécution, il est souvent demandé de saisir certaines informations utiles à l'application.

Il peut arriver que vous stoppiez pour différentes raisons cette saisie d'informations.

Lors d'une prochaine exécution de votre application, il vous sera demandé de compléter cette saisie d'informations inachevée.

Le pattern stratégie peut être utile pour définir quelles sont les données restantes à saisir.

Voici un exemple d'implémentation en Java.

Définissons d'abord notre <Strategy Manager>, c'est notre point d'entrée.

public class StrategyManager {
private static StrategyManager instance = null;

// contexte d'exécution
private StrategyContext ctx;

/**
* @return instance StrategyManager

* @throws Exception
*/
public static StrategyManager getInstance() throws Exception {
if (instance == null)
instance = new StrategyManager();

return instance;
}

/**
* exécuter stratégie de lancement
*
* @throws Exception
*/
public void execCtx() throws Exception {
ctx.exec();
}

/**
* @throws Exception
*/
private StrategyManager()
throws Exception {
ctx = new StrategyContext();

  boolean etat = getEtat();

if (etat == 1) 
ctx.setStrategy(new Launch1());
else if (etat == 2)
ctx.setStrategy(new Launch2());
 else
// erreur
}

private int getEtat() {
   int etat = 0;

   // définir l'état qui correspond au contexte que vous souhaitez traiter

  return etat;


}

Vous avez noté que nous avons utilisé un autre pattern, le pattern Singleton. De cette façon nous manipulons qu'une seule instance de notre manager.

Définissons la gestion du contexte <Strategy Context>.

public class StrategyContext {
private IStrategy strategy;

/**
* fixe la stratégie

* @param strategy
*            : stratégie à appliquer
*/
public void setStrategy(IStrategy strategy) {
this.strategy = strategy;
}

/**
* exécuter stratégie sélectionnée

         * @return 

* @throws Exception
*/
public boolean exec() throws Exception {
return strategy.go();
}
}

public interface IStrategy {

/**
* exécuter le code propre à la stratégie choisie

* @throws Exception
*/
public boolean go() throws Exception;
}

Définissons maintenant les différents algorithmes qui peuvent être utilisés selon le contexte.

public class Launch1 implements IStrategy {
public Launch1() {
super();
}

/**
* exécuter stratégie lancement de type 1
*/
@Override
public boolean go() throws Exception {
           boolean resp = true;

           // votre code...

          return resp;
        }
}

public class Launch2 implements IStrategy {
public Launch2() {
super();
}

/**
 * exécuter stratégie lancement de type 2
 */
@Override
public boolean go() throws Exception {
           boolean resp = true;

           // votre code...

          return resp;
        }
}

La dernière étape : comment utiliser notre pattern stratégie ?

StrategyManager instance = StrategyManager.getInstance();

boolean resp = instance.execCtx();

if (!resp) {
  // erreur
}

Un des avantages de ce pattern est la possibilité d'ajouter ou de modifier un algorithme facilement sans réellement toucher au "corps" du traitement.

Aucun commentaire:

Enregistrer un commentaire