Design Pattern - 02/24 - Observer

ImageCalendarCreation   Crée le : 26/01/2011 Calendar   Modifié le : 30/01/2011 ImageOwner   Par : Proteus ImageVisites   Vue : 168 CommentaireCount   Commentaire(s) : 0

Introduction


Nous avons de plus en plus de fenêtres dans nos applications, chacune de ces fenêtres remplissant un rôle bien précis pour l’utilisateur il se peut cependant que ces vues surveillent les mêmes données. A plusieurs reprises j’ai rencontré du code où certaines méthodes étaient confiées à un « Timer » qui déclenchait ces dernières à un instant « t ». Au delà du problème de maintenabilité que cela pose, cette solution pointe également du doigt la consommation matérielle relative à ce rafraichissement. A tort ou à raison il est parfaitement inutile d’avoir un déclenchement de méthode si cette dernière n’apporte rien à l’application. Le design pattern « Observer » répond au besoin d’un déclenchement de méthodes des vues justifié par une véritable action.

Définition


Le Design Pattern Observer a pour but de surveiller un état pour le compte d'objets qui se sont enregistrés pour être informés d'un changement.

Cas pratique


Pour notre test nous allons faire une toute petite application qui aura pour but de montrer comment l’observer peut agir sur des méthodes qui ne sont pas siennes et également de comprendre les mécanismes de surveillance, enregistrements et dés-enregistrements. Pour implémenter le Design Pattern Observer, nous aurons besoin :

  • d'une classe centrale l’observer.
  • d'une interface qu’implémentera les vues afin de définir les méthodes que va déclencher l’Observer.
  • et d'au moins deux vues qui implémentent l’interface citée au dessus.

L’Interface


Elle sera implémentée par toutes les vues qui souhaitent être sous l’effet de l’Observer. Ici notre interface va demander l’implémentation d’une propriété « Message » et d’une méthode « ShowMessage »

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DPObserver.Interfaces
{
    public interface IObserverCustom
    {
        #region Proprietes
        string Message { get; set; }

        #endregion

        #region Methodes
        void ShowMessage(String message);

        #endregion
    }
}

La Classe


Il s’agit ici de la classe de base, elle aura pour but d’enregistrer les vues qui souhaitent être sous l’effet de l’Observer en utilisant les méthodes « Suscribe » et « UnSuscribe » (pour le dés enregistrement). Ici on voit que les vues seront stockées dans une List<> sous la forme Observer. Nous simulons une donnée importante dans la « String » DataBaseMessage. La modification de cette propriété aura pour but de déclencher la méthode « CallSuscribers ». Cette méthode va parcourir la liste des vues qui s’y sont inscrites et appeler la méthode « ShowMessage » de chacune d’entres elles.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using DPObserver.Interfaces;

namespace DPObserver.Classes
{
    public class ObserverCustom
    {
        #region Variable
        private static readonly ObservableCollection listOfObserver = 
              new ObservableCollection();
        private static string dataBaseMessage;

        #endregion

        #region Proprietes
        public static string DataBaseMessage
        {
            get
            {
                return ObserverCustom.dataBaseMessage;
            }
            set
            {
                ObserverCustom.dataBaseMessage = value;
                CallSuscribers(value);
            }
        }

        #endregion

        #region Methodes
        #region Public
        public static bool Suscribe(IObserverCustom obsever)
        {
            if (!listOfObserver.Contains(obsever))
                listOfObserver.Add(obsever);
            return true;
        }
        public static bool UnSuscribe(IObserverCustom obsever)
        {
            if (!listOfObserver.Contains(obsever))
                return false;
            listOfObserver.Remove(obsever);
            return true;
        }

        #endregion

        #region Private
        private static void CallSuscribers(String message)
        {
            foreach (IObserverCustom observer in listOfObserver)
            {
                observer.ShowMessage(message);
                observer.Message = message;
            }
        }

        #endregion

        #endregion
    }
}

Vue1


Ci-dessous le code « Behind » de notre Vue principale. Ici nous implémentons l’interface « IObserver » c’est cette implémentation d’interface qui va nous permettre d’enregistrer notre « Form » auprès de notre Observer. Première chose que l’on fait on implémente les méthodes de l’interface, ensuite il faut enregistrer la vue avec la méthode « Subscribe », quand on quitte l’application on utilise la méthode « UnSubscribe » pour des-enregistrer la vue. Nous codons ensuite l’élément qui va déclencher un appel de notre Observer. Plus haut nous avons vu que la modification de la propriété « DataBaseMessage » était le déclencheur de l’Observer. Nous implémentons donc ce code dans le de notre bouton.

using System;
using System.Windows;
using DPObserver.Interfaces;

namespace DPObserver
{
    public partial class MainWindow : Window, IObserverCustom
    {
        #region Variables
        private string message = "";

        #endregion

        #region Proprietes
        public string Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }

        #endregion

        #region Constructeurs
        public MainWindow()
        {
            InitializeComponent();
            DPObserver.Classes.ObserverCustom.Suscribe(this);
        }

        #endregion

        #region Methodes
        public void ShowMessage(string message)
        {
            MessageBox.Show(String.Format("Le message '{0}' a été envoyé par l'observer.", message),
            "Custom Observer", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        #endregion

        private void CommandButtonModifier_Click(object sender, RoutedEventArgs e)
        {
            DPObserver.Classes.ObserverCustom.DataBaseMessage = "test";
        }
    }
}

Enchainements


Quand on lance l’application nous avons nos deux vues qui apparaissent. On enregistre chacune des vues auprès de l’Observer. L’Observer va alors stocker ces vues dans une liste. Lorsque l’on clique sur l’une des commandes de l’une des vues, nous modifions la donnée que notre Observer surveille pour les vues. Observer parcourt la liste des Observer qui se sont enregistrés et déclenche les méthodes implémentées par l’interface. Si vous décidez d’ajouter une nouvelle vue, vous n’aurez qu’ implémenter votre interface et l’enregistrer auprès de votre Observer à son ouverture. Le reste l’Observer s’en charge.

Conclusion


L’exemple que nous avons utilisé ici est des plus simples, le principal ici, étant de bien comprendre que l’observer a pour but de déclencher des opérations pour les vues qui se sont enregistré auprès de lui. Vous savez maintenant implémenter le design pattern Observer, au fil des développements que vous aurez à faire vous vous apercevrez que ce Design Pattern est très fréquemment utilisé. Si on prend l’exemple sur ce site du modèle MVC vous en comprendrez l’utilité.

 

Editer le Message Supprimer le Message ContactMe   Contactez-moi


Laisser un commentaire