RSS

Tag Archives: C#

[C#][Design Patterns] La Commande (Command)

Pour continuer la liste des patrons de conception, je vais maintenant vous exposer celui de la Commande.

C’est un patron de conception qui permet de réaliser de façon simple les différentes actions d’un objet. D’un côté l’objet qui va être l’invocateur de l’action et la commande qui va elle, être le réalisateur de l’action car c’est elle qui va en avoir les tenants et les aboutissants. Autrement dit, c’est l’objet qui à la ligne d’appel de l’action et la commande qui a le code de l’action.

Mais tout cela s’explique et se comprend beaucoup mieux avec un exemple 😀

L’interrupteur

Je vais vous montrer par un concept quotidien, l’interrupteur, comment fonctionne et s’implémente ce patron de conception.

L’interface Commande

Avant tout, il nous faut définir l’interface du patron de conception. Rien de bien compliqué, elle ne se constitue que d’une méthode appelée execute()

   1:  public interface ICommand
   2:  {
   3:      void execute();
   4:  }

La classe Interrupteur

Désormais nous pouvons réaliser la classe de l’interrupteur qui va être l’invocateur de l’action

   1:  public class Interrupteur
   2:  {
   3:      public ICommand PushUpCommand { get; private set; }
   4:      public ICommand PushDownCommand { get; private set; }
   5:   
   6:      public Interrupteur(ICommand pushUpCommand, ICommand pushDownCommand)
   7:      {
   8:          this.PushUpCommand = pushUpCommand;
   9:          this.PushDownCommand = pushDownCommand;
  10:      }
  11:   
  12:      public void PushUp() { this.PushUpCommand.execute(); }
  13:   
  14:      public void PushDown() { this.PushDownCommand.execute(); }
  15:  }

Dans cette classe, nous avons défini deux méthodes reflétant l’appui sur le bouton en position haute (~ PushUp) et en position basse (~ PushDown)

La classe Light

Nous allons maintenant écrire la classe du récepteur de l’action, la lumière.

   1:  public class Light
   2:  {
   3:      public string Name { get; private set; }    
   4:   
   5:      public Light(string name)
   6:      {
   7:          this.Name = name;
   8:      }
   9:   
  10:      public void LightOn()
  11:      {
  12:          Console.WriteLine(this.Name + " | Je suis allumée");
  13:      }
  14:   
  15:      public void LightOff()
  16:      {
  17:          Console.WriteLine(this.Name + " | Je suis éteinte");
  18:      }
  19:  }

Dans cette classe, nous avons défini deux méthodes permettant l’allumage et l’extinction de la lumière.

La classe LightOnCommand

Maintenant, nous allons écrire la commande pour allumer une lumière

   1:  public class LightOnCommand : ICommand
   2:  {
   3:      public Light LightReceipt { get; private set; }
   4:   
   5:      public LightOnCommand(Light lightReceipt)
   6:      {
   7:          this.LightReceipt = lightReceipt;
   8:      }
   9:   
  10:      public void execute()
  11:      {
  12:          LightReceipt.LightOn();
  13:      }
  14:  }

Dans cette classe, remarquez le stockage du récepteur dans la commande. Cela est important car c’est grâce à cette imbrication du récepteur dans la commande que l’on comprend le rôle concret de celle-ci dans le patron de conception.

La classe LightOffCommand

Ensuite, on écris la commande pour l’extinction.

   1:  public class LightOffCommand : ICommand
   2:  {
   3:      public Light LightReceipt { get; private set; }
   4:   
   5:      public LightOffCommand(Light lightReceipt)
   6:      {
   7:          this.LightReceipt = lightReceipt;
   8:      }
   9:   
  10:      public void execute()
  11:      {
  12:          LightReceipt.LightOff();
  13:      }
  14:  }

Le programme d’appel

Maintenant que nous avons tous les morceaux de notre patron de conception, nous allons réaliser le chef d’orchestre qui va mettre en marche ce dernier et montrer comment celui-ci fonctionne.

   1:  public class Program
   2:  {
   3:      public static void Main(string[] args)
   4:      {
   5:          //Les lumières
   6:          Light lightSalleManger = new Light("Salle à manger");
   7:          Light lightSalon = new Light("Salon");
   8:   
   9:          //Commandes pour la lumière de la salle à manger
  10:          LightOnCommand commandUpSalleManger = new LightOnCommand(lightSalleManger);
  11:          LightOffCommand commandDownSalleManger = new LightOffCommand(lightSalleManger);
  12:          //Commandes pour la lumière du salon
  13:          LightOnCommand commandUpSalon = new LightOnCommand(lightSalon);
  14:          LightOffCommand commandDownSalon = new LightOffCommand(lightSalon);
  15:   
  16:          //Les interrupteurs
  17:          Interrupteur interSalleManger = new Interrupteur(commandUpSalleManger, commandDownSalleManger);
  18:          Interrupteur interSalon = new Interrupteur(commandUpSalon, commandDownSalon);
  19:   
  20:          //Lancement de la séquence d'allumage/extinction des lumières
  21:          interSalleManger.PushUp();
  22:          interSalon.PushUp();
  23:          interSalon.PushDown();
  24:          interSalon.PushUp();
  25:          interSalon.PushDown();
  26:          interSalleManger.PushDown();
  27:   
  28:          Console.ReadKey() //Pour voir le résultat dans la console
  29:      }
  30:  }

Dans cet exemple de mise en oeuvre, vous remarquez très certainement que ce n’est pas très exactement comme cela que fonctionne un interrupteur car nous avons délibérement appeler PushUp(), PushDown().

En effet, si vous vous amusez à mettre deux fois interSalleManger.PushUp(), cela va fonctionner et vous donnez deux fois une instruction d’allumage. Un cas d’usage qui ne peut pas arriver en réel.

Amélioration du concept en gardant le patron de conception

Reprenons notre Interrupteur afin d’améliorer son fonctionnement

   1:  public class Interrupteur
   2:  {
   3:      private Queue PushCommands { get; set; }
   4:   
   5:      public Interrupteur(ICommand pushUpCommand, ICommand pushDownCommand)
   6:      {
   7:          PushCommands = new Queue(2);
   8:          PushCommands.Enqueue(pushUpCommand);
   9:          PushCommands.Enqueue(pushDownCommand);
  10:      }
  11:   
  12:      public void Push()
  13:      {
  14:          //On exécute la prochaine ICommand de la Queue
  15:          ICommand nextCommand = PushCommands.Peek();
  16:          nextCommand.execute();
  17:          //On remet la ICommand à la fin de la Queue afin de la réexécuter plus tard
  18:          PushCommands.Enqueue(nextCommand);
  19:      }
  20:  }

Nous avons supprimer les deux commandes pour les remplacer par une Queue. Cela nous permet ainsi dans la méthode Push de mieux gérer l’état de l’interrupteur et de façon interposer de la lumière.

On corrige maintenant le code du chef d’orchestre afin de s’aligner sur les changements effectués dans l’Interrupteur

   1:  public class Program
   2:  {
   3:      public static void Main(string[] args)
   4:      {
   5:          //Les lumières
   6:          Light lightSalleManger = new Light("Salle à manger");
   7:          Light lightSalon = new Light("Salon");
   8:   
   9:          //Commandes pour la lumière de la salle à manger
  10:          LightOnCommand commandUpSalleManger = new LightOnCommand(lightSalleManger);
  11:          LightOffCommand commandDownSalleManger = new LightOffCommand(lightSalleManger);
  12:          //Commandes pour la lumière du salon
  13:          LightOnCommand commandUpSalon = new LightOnCommand(lightSalon);
  14:          LightOffCommand commandDownSalon = new LightOffCommand(lightSalon);
  15:   
  16:          //Les interrupteurs
  17:          Interrupteur interSalleManger = new Interrupteur(commandUpSalleManger, commandDownSalleManger);
  18:          Interrupteur interSalon = new Interrupteur(commandUpSalon, commandDownSalon);
  19:   
  20:          //Lancement de la séquence d'allumage/extinction des lumières
  21:          interSalleManger<strong>.Push()</strong>;
  22:          interSalon<strong>.Push()</strong>;
  23:          interSalon<strong>.Push()</strong>;
  24:          interSalon<strong>.Push()</strong>;
  25:          interSalon<strong>.Push()</strong>;
  26:          interSalleManger<strong>.Push()</strong>;
  27:   
  28:          Console.ReadKey() //Pour voir le résultat dans la console
  29:      }
  30:  }

Cette fois-ci, le concept se rapproche de la réalité et on ne peut plus « tricher » sur l’état de ce dernier.

Comment dériver l’exemple pour d’autres cas d’usages ?

Nous avons ici étudier le cas de la lumière mais il pourrait se dériver également pour d’autres cas d’usages tel que pour la TV.

La classe Tv

   1:  public class Tv
   2:  {
   3:      public string Name { get; private set; }    
   4:   
   5:      public Tv(string name)
   6:      {
   7:          this.Name = name;
   8:      }
   9:   
  10:      public void TvOn()
  11:      {
  12:          Console.WriteLine(this.Name + " | Je suis allumée");
  13:      }
  14:   
  15:      public void TvOff()
  16:      {
  17:          Console.WriteLine(this.Name + " | Je suis éteinte");
  18:      }
  19:  }

La classe TvOnCommand

   1:  public class TvOnCommand: ICommand
   2:  {
   3:      public Tv TvReceipt { get; private set; }
   4:   
   5:      public TvOnCommand(Tv tvReceipt)
   6:      {
   7:          this.TvReceipt = tvReceipt;
   8:      }
   9:   
  10:      public void execute()
  11:      {
  12:          TvReceipt.TvOn();
  13:      }
  14:  }

La classe TvOffCommand

   1:  public class TvOffCommand: ICommand
   2:  {
   3:      public Tv TvReceipt { get; private set; }
   4:   
   5:      public TvOffCommand(Tv tvReceipt)
   6:      {
   7:          this.TvReceipt = tvReceipt;
   8:      }
   9:   
  10:      public void execute()
  11:      {
  12:          TvtReceipt.TvOff();
  13:      }
  14:  }

Le chef d’orchestre

   1:  public class Program
   2:  {
   3:      public static void Main(string[] args)
   4:      {
   5:          //Les TV
   6:          Light tvSalleManger= new Light("TV Salle à manger");
   7:          Light tvSalon= new Light("TV Salon");
   8:   
   9:          //Commandes pour la tv de la salle à manger
  10:          TvOnCommand commandUpSalleManger = new TvOnCommand (tvSalleManger);
  11:          TvOffCommand commandDownSalleManger = new TvOffCommand(tvSalleManger);
  12:          //Commandes pour la tv du salon
  13:          TvOnCommand commandUpSalon = new TvOnCommand (tvSalon);
  14:          TvOffCommand commandDownSalon = new TvOffCommand(tvSalon);
  15:   
  16:          //Les interrupteurs
  17:          Interrupteur interTvSalleManger= new Interrupteur(commandUpSalleManger, commandDownSalleManger);
  18:          Interrupteur interTvSalon = new Interrupteur(commandUpSalon, commandDownSalon);
  19:   
  20:          //Lancement de la séquence d'allumage/extinction des lumières
  21:          interTvSalleManger<strong>.Push()</strong>;
  22:          interTvSalon <strong>.Push()</strong>;
  23:          interTvSalon <strong>.Push()</strong>;
  24:          interTvSalon <strong>.Push()</strong>;
  25:          interTvSalon <strong>.Push()</strong>;
  26:          interTvSalleManger<strong>.Push()</strong>;
  27:      }
  28:  }

Conclusion

J’espère que cet article vous aura permis de mieux comprendre l’intérêt de ce patron de conception et surtout voir dans quels usages il peut s’utiliser. Le prochain patron de conception que je vais abordé sera le patron de conception Etat (State).


Voir aussi

 

Tags: , , ,

[C#][Design Patterns] L’Etat (State)

Nous revoilà ensemble pour découvrir après la Commande, le patron de conception Etat.

Ce patron de conception permet de modifier l’état d’un contexte donné sans en changer l’implémentation. Pour cela, le patron de conception Etat se compose d’une classe Contexte qui contient l’objet Etat qui va être amené à évoluer.

Pour mieux comprendre comment cela s’organise et s’emboîte, rien de tel qu’un bon exemple 😉

Le tableau, la craie et la brosse

Nous allons revenir en enfance et nous rappeler de nos bons vieux amis que personne ne voulait aller utiliser sur demande du professeur :-D.

Nous aurons donc la classe Tableau qui sera notre contexte, la classe Craie et la classe Brosse qui seront nos objets Etat.

L’interface des Etat

Mais avant tout, il nous faut définir l’interface de nos objets Etat. Pour cela, nous allons écrire l’interface IOutil qui sera la base de notre Craie et de notre Brosse.

public interface IOutil
{
    void mousePressed(MouseEventArgs e);

    void mouseMove(MouseEventArgs e);
}

Les objets Etat

Maintenant que nous avons l’interface, nous pouvons définir nos objets Etat et implémenter le code à exécuter pour les actions définies dans l’interface.

Craie

public class Craie : IOutil
{
    public void mousePressed(MouseEventArgs e)
    {
        if(e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            //Ecrire un point sur le tableau
        }
    }

    public void mouseMove(MouseEventArgs e)
    {
        if(e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            //Ecrire un point à chaque coordonnée de la souris sur le tableau
            //dès lors que le clic gauche est pressé
        }
    }
}

Je n’ai pas écris le code intérieur des méthodes car cela demande plus que les classes expliquées ici :-P. Néanmoins, je reviendrai pour vous donner un projet exemple complet.

Brosse

public class Brosse : IOutil
{
    public void mousePressed(MouseEventArgs e)
    {
        if(e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            //Efface un point sur le tableau
        }
    }

    public void mouseMove(MouseEventArgs e)
    {
        if(e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            //Efface un point à chaque coordonnée de la souris sur le tableau
            //dès lors que le clic gauche est pressé
        }
    }
}

Tout comme pour l’objet Craie, le code n’est pas complet et est là juste à titre illustratif du patron de conception.

Le contexte

Tableau

Maintenant que nous avons réalisé l’interface et les classes Etat, nous pouvons passer à la classe Contexte, le Tableau.

public class Tableau
{
    public IOutil Outil { get; set; }

    protected override void OnMouseClick(MouseEventArgs e)
    {
        Outil.mousePressed(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        Outil.mouseMove(e);
    }
}

Comme on peut le voir dans cet exemple, les évènements de la souris sur le Tableau sont délégués à l’Etat afin qu’il réalise les actions qui lui sont propre.

Conclusion

Le patron de conception Etat est un patron assez puissant dans son exécution et permet de décomplexifier certains enchaînements qui pourrait demander des calculs mathématiques complexes, des stockages de variables conséquents. Il répond très simplement à la mise en place de machine à états et est également très utilisé dans le domaine du jeu vidéo notamment pour les jeux de plateau qui sont très friants de systèmes à états.

Voilà, j’espère que ce patron de conception vous sera démystifier et saura convenir à d’éventuels besoins actuels ou futurs.

Je continuerai ma saga des patrons de conception avec le patron Visiteur (Visitor) qui deviendra vite un ami incontournable 😉


Voir aussi

 

Tags: , , ,

[C#][HowTo] Afficher une page statique durant le PreLoad

Dans un précédent article, je vous expliquait comment implémenter le PreLoad. Dans cet article, je vais vous montrer comment rediriger vos utilisateurs durant ce pré-chargement de votre application.

En effet, durant le pré-chargement les requêtes clientes sont ignorées et mises en attente sur le serveur jusqu’à ce que celui-ci soit disponible. Selon le temps de votre pré-chargement, cela peut vous amener à avoir des tickets d’incidents, des appels non souhaités du fait que cet évènement de pré-chargement est dans le cycle de vie de votre application mais que seul vous êtes au courant de la chose.

C’est pour cela qu’il est toujours préférable de prévenir les utilisateurs d’une indisponibilité ponctuelle de l’application.

Read the rest of this entry »

 

Posted by on 24 septembre 2012 in .Net, ASP.Net, C#.Net, Codes, Outils, Programmation, Tools

Leave a comment

Tags: , , , , ,

[C#][HowTo] Comment instancier un objet d’un type générique

Vous connaissez les génériques ? Non ? Je vous invite à regarder plus en détails ce que c’est grâce à la documentation MSDN.

Ces types sont très utiles et sont clairement utilisés dans les types que vous connaissez déjà :

  • List<T>
  • HashSet<T>
  • Dictionary<T, U>

Cela vous donne un aperçu de l’étendu de son usage au sein même du Framework. Il est également possible de les utiliser dans nos propres objets et dans certains cas il nous faut les construire de façon dynamique.

Read the rest of this entry »

 

Posted by on 13 septembre 2012 in .Net, C#.Net, Codes, Programmation, Tutoriel

Leave a comment

Tags: , , , ,

[C#][HowTo] Comment déclarer un paramètre de taille variable (params)

Vous est-il déjà arriver d’avoir ce genre de méthodes …

public void searchValues(string s1) { ... }
public void searchValues(string s1, string s2) { ... }
public void searchValues(string s1, string s2, string s3) { ... }

… parce que vous ne savez pas combien de paramètres vous pouvez avoir ?

Il y a une solution à cela, la déclaration d’un paramètre « illimité »

Read the rest of this entry »

 

Posted by on 13 juin 2012 in .Net, C#.Net, Codes, Programmation, Tutoriel

Leave a comment

Tags: , , ,

[C#][HowTo] Créer une extension de code (helper)

Regardez bien ce code, ne remarquez vous rien de bizarre ?

text as string = "13/06/2012";
text.ToDateTime();

Quoi ? Ça n’est pas possible de faire cela sur un objet string ?!

Eh bien si détrompez-vous ;-). Il suffit pour cela d’utiliser ce qui s’appelle des helpers autrement dit en français des extensions de code.

Read the rest of this entry »

 

Tags: , , , ,

[C#][Design Patterns] La Fabrique (Factory)

Continuons dans les patrons de conception avec la Fabrique.

Ce patron de conception est d’abord destiné aux objets dérivés d’une classe abstraite pour qui l’on permet la construction sans que l’appelant n’ait connaissance des dérivés.

Mais cela sert également à centraliser la construction d’objets, de résoudre la construction d’objet par rapport à diverses variations de l’environnement.

C’est ce que je vais essayer de vous illustrer dans ce post afin de mieux comprendre son intérêt.

Read the rest of this entry »

 

Tags: , , ,