IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Design Patterns Discussion :

[Android] Design pattern Factory et notes de musique


Sujet :

Design Patterns

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut [Android] Design pattern Factory et notes de musique
    Bonjour,

    Je suis assez novice avec l'utilisation des design patterns, mais j'essaie de me familiariser avec. Je réalise un projet perso Android pour me rôder à la conception logicielle. L'activité Android que je construis représente un diagramme de notes. Le but est pour moi d'afficher toutes les notes présentes sur le manche d'une guitare comme suit:
    Nom : notes-on-guitar-fretboard_0.jpg
Affichages : 697
Taille : 35,4 Ko

    Chaque note serait cliquable pour jouer la note en question au travers d'une méthode disons playSound().
    Je me retrouve donc avec une classe abstraite Note, dont hérite un grand nombre de classe (la note et les déclinaisons de celle-ci en dièse et en bémol), par exemple SolNote, SolSharpNote, SolFlatNote etc...
    Je me suis donc demandé si l'utilisation d'une NoteFactory n'était pas judicieuse pour masquer l'appel à des "Note note = new SolNote" lors de l'attribution des notes de musique à la vue.
    Ainsi si je change l'implémentation des notes dans le futur en regroupant les dièses et les bémols sous une même classe SolNote, l'appel pour instancier cette note restera inchangé ("NoteFactory.getNote("G#")") et il me suffit juste de modifier la Factory, plutôt que de revoir toutes les instanciations de notes.

    Du coup je voulais avoir un avis sur ma compréhension du design pattern Factory, savoir s'il est raisonnable d'envisager mon problème sous cet angle.

    Merci d'avance pour toute l'aide apportée

  2. #2
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 917
    Points
    2 917
    Par défaut
    Bonjour,

    Beaucoup de choses à dire

    • C'est un projet exemple pour apprendre ? Une classe par note spécifique, je ne suis pas persuadé que les applis de musique soient conçues comme ça dans la réalité.


    • A quel pattern Factory fais-tu allusion en particulier (lien ?)


    l'appel pour instancier cette note restera inchangé ("NoteFactory.getNote("G#")") et il me suffit juste de modifier la Factory, plutôt que de revoir toutes les instanciations de notes
    Ce n'est pas l'utilité première à laquelle on pense pour une Factory. Là, tu transformes une valeur qui appartient à un univers de représentation particulier (la string "G#") en une instance de classe. Du coup c'est une sorte de Translator en plus d'être un pattern créationnel.

    Si, dans tes specs, tu as forcément en input des chaines du type "G#", avoir une Factory ou autre chose ne change rien dans le fait qu'il faille traduire cela en objets.

    Si tu as eu l'idée d'introduire la notation "G#" uniquement pour ta méthode de Factory, pour moi c'est inutile. Pour le code client, savoir qu'il faut passer "G#" à une méthode de Factory ou savoir qu'il faut faire new GSharpNote(), c'est du pareil au même au niveau maintenabilité (sauf qu'en plus tu te trimballes des chaînes de caractères qui ne sont pas type-safe).

    En général, on utilise le concept d'(Abstract) Factory pour délester le code client de la connaissance de l'objet concret qu'il va obtenir. C'est une forme d'inversion de dépendance : le code consommateur ne dépend plus d'une classe concrète mais d'une abstraction, ce n'est plus lui qui décide de l'objet concret qui va être créé mais un tiers extérieur (celui qui lui a passé la Factory).

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Tout d'abord merci beaucoup de ta réponse qui m'amène à revoir encore et encore les cours de pattern du coup
    Oui c'est un projet personnel pour essayer d'être confronter à des problèmes de conception et c'est un outil qui me servira potentiellement dans l'apprentissage de la guitare (lier l'utile à l'agréable? )

    Je pensais que le fait d'utiliser la fabrique concrète (https://abrillant.developpez.com/tut...oduction/#L3.1) permettait d'ajouter de la flexibilité dans l'instanciation des objets. Etant donné que l'utilisateur de la Factory ne connait pas les classes utilisées au sein de la Factory, ça permettait de pouvoir "à loisir" de changer l'implémentation des classes concernées.

    Du coup j'ai changé l'implémentation de ma classe Note, qui contient désormais deux attributs issues de deux enum NoteName("A","B","C",...), NoteAlteration("#","b",...), je ne sais pas si c'est plus intelligent de procéder comme ça.

    J'avoue être un peu décontenancé par ces histoires de fabrique et fabrique abstraite. Je comprends un peu l'idée, mais savoir quand l'utiliser et quand ne pas l'utiliser cela reste un peu mystérieux. J'ai peut être trop d'entrain envers les design pattern, et je finis par vouloir en mettre partout
    C'est d'ailleurs pour ça que je me suis lancé dans ce projet, pour essayer de concevoir un outil maintenable et propre

  4. #4
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 917
    Points
    2 917
    Par défaut
    Je reste perplexe à la lecture du paragraphe du tutoriel. Ca me paraît être un exemple d'école pour montre le côté créationnel de la Factory, mais j'ai rarement vu ça dans le monde réel.

    Pour améliorer la maintenabilité du code, on se réfère souvent au Open/Closed principle : pour ajouter plus de fonctionnalités, une classe doit être ouverte à l'extension (en gros, le sous-classage) mais fermée à la modification.

    Dans le tutoriel, il est indiqué comme bénéfice de la Factory :

    lors d'une évolution l'utilisateur pourra changer facilement la nature des objets (avec d'autres classes implémentant les interfaces Point et Line...)
    J'ai du mal à voir de quel type d'évolution il s'agit, mais on va dire qu'on pourrait changer de librairie d'affichage et retourner des MySuperGraphicsLine au lieu des LineImpl.

    => la Factory n'est absolument pas closed for modification, il faut l'ouvrir et modifier son code pour remplacer les new LineImpl par des new MySuperGraphicsLine.

    Autre chose aurait été d'avoir une Factory abstraite mère dont auraient hérité une CanvasFactoryImpl et une MySuperGraphicsCanvasFactory. Ca c'est open for extension c'est à dire qu'à chaque changement de techno graphique on ajoute une nouvelle classe Factory sans toucher aux autres.

  5. #5
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 917
    Points
    2 917
    Par défaut
    Citation Envoyé par Exomus Voir le message
    J'avoue être un peu décontenancé par ces histoires de fabrique et fabrique abstraite. Je comprends un peu l'idée, mais savoir quand l'utiliser et quand ne pas l'utiliser cela reste un peu mystérieux.
    Pour donner un exemple de chaque :

    Factory Method

    Imaginons que je suis dans du code de tests unitaires pour les carrés et les rectangles. J'ai une propriété à tester qui vaut pour les deux formes géométriques : l'aire est égale à Largeur x Hauteur.

    Ma classe de test parente va définir le test (aire = LxH) et une Factory Method makeObjectToTest() qui va être implémentée par les deux classes dérivées CarréTest et RectangleTest.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class BaseTest 
    {
      @Test
      public void TestAire() {
        Rectangle objectToTest = makeObjectToTest();
        assertEquals(objectToTest.getLargeur() * objectToTest.getHauteur(), objectToTest.getAire());
      }
     
      abstract Rectangle makeObjectToTest(); // Factory Method !!!
    }
     
    public class RectangleTest extends BaseTest
    {
      Rectangle makeObjectToTest()
      {
        return new RectangleImpl(...);
      }
    }
     
    public class CarreTest extends BaseTest
    {
      Rectangle makeObjectToTest()
      {
        return new CarreImpl(...);
      }
    }

    Ici, l'intérêt est que BaseTest ignore totalement si c'est un carré ou un rectangle qui va être utilisé, et pourtant peut définir des tests (en d'autres termes des propriétés) qui doivent être vérifiés pour les deux. On n'a pas à réécrire le même test deux fois.

  6. #6
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 917
    Points
    2 917
    Par défaut
    Abstract Factory

    Je l'utilise très rarement, uniquement dans les cas où je veux pouvoir créer des objets parmi une famille d'objets et où je veux maîtriser entièrement leur cycle de vie.

    Supposons que je sois dans un programme qui veut dialoguer avec un serveur. via un client réseau. Dans mon fichier de configuration, il y aura un paramètre pour indiquer le protocole : TCP ou UDP (ou d'autres à rajouter plus tard) mais je ne le sais pas à l'avance.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public class MyCode {
      private NetworkClientFactory factory;
     
      public MyCode(NetworkClientFactory factory) {
        this.factory = factory; // injection d'une factory, on ne sait pas à l'avance de quel type concret
      }
     
      public void doStuff() {
        NetworkClient client = factory.createClient(); // ouvre une connexion réseau, fait plein de trucs gourmands donc j'ai besoin de maîtriser à quel moment je l'appelle
        client.send("ping");
        System.out.println(client.receive());	
        client.close();
      }
    }
     
    public abstract class NetworkClientFactory { // Ma fabrique abstraite
      abstract NetworkClient createClient();
    }
     
    public class TcpClientFactory extends NetworkClientFactory {
      public NetworkClient createClient() {
        return new TcpClient(...);
      }
    }
     
    public class UdpClientFactory extends NetworkClientFactory {
      public NetworkClient createClient() {
        return new UdpClient(...);
      }
    }
     
    public abstract class NetworkClient {
      abstract void send(String message);
      abstract String receive();
      abstract String close();
    }
     
    public class UdpClient {
      // ...
    }
     
    public class TcpClient {
      // ...
    }

    L'intérêt est que je peux rajouter un troisième protocole en écrivant simplement une nouvelle classe dérivée de NetworkClient et une de NetworkClientFactory, sans toucher à MyCode.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Merci pour toutes ces réponses apportées, ça va me permettre de digérer ces concepts, et mieux pouvoir les aborder notamment cette année où l'on va débuter les cours de design pattern dans ma formation.

    Je comprends un peu mieux l'utilité des factory, et surtout des abstract factory qui restait pour moi un grand mystère.

    Merci encore du temps que tu as passé à rédiger ces messages

Discussions similaires

  1. design pattern factory
    Par olive_le_malin dans le forum C++
    Réponses: 2
    Dernier message: 23/08/2007, 16h31
  2. Classe + design pattern factory
    Par Rodrigue dans le forum C++
    Réponses: 8
    Dernier message: 07/11/2006, 15h42
  3. [Conception]Design Pattern Factory ?
    Par ®om dans le forum Logging
    Réponses: 8
    Dernier message: 13/09/2006, 11h20
  4. [Fabrique] [Java] Design Pattern Factory
    Par SkyBioSS dans le forum Design Patterns
    Réponses: 3
    Dernier message: 24/05/2006, 15h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo