CodeGym /Blog Java /Random-FR /Modèle de conception de l'adaptateur
Auteur
Pavlo Plynko
Java Developer at CodeGym

Modèle de conception de l'adaptateur

Publié dans le groupe Random-FR
Salut! Aujourd'hui, nous aborderons un nouveau sujet important : les modèles de conception . Quels sont ces motifs ? Je pense que vous devez connaître l'expression " ne réinventez pas la roue ". En programmation, comme dans bien d'autres domaines, il existe un grand nombre de situations courantes. Au fur et à mesure que le développement de logiciels a évolué, des solutions prêtes à l'emploi qui fonctionnent ont été créées pour chacun d'entre eux. Ces solutions sont appelées patrons de conception. Par convention, un modèle est une solution formulée comme ceci : "si vous devez faire X dans votre programme, alors c'est la meilleure façon de le faire". Il existe de nombreux modèles. L'excellent livre "Head First Design Patterns", qu'il faut absolument connaître, leur est dédié. Modèle de conception d'adaptateur - 2En termes concis, un modèle se compose d'un problème commun et d'une solution correspondante qui peut être considérée comme une sorte de norme. Dans la leçon d'aujourd'hui, nous rencontrerons l'un de ces modèles : Adaptateur. Son nom dit tout, et vous avez rencontré des adaptateurs à plusieurs reprises dans la vraie vie. Certains des adaptateurs les plus courants sont les lecteurs de cartes dont disposent de nombreux ordinateurs et ordinateurs portables. Modèle de conception d'adaptateur - 3Supposons que nous ayons une sorte de carte mémoire. Donc quel est le problème? Il ne sait pas comment interagir avec l'ordinateur. Ils ne partagent pas une interface commune. L'ordinateur a un port USB, mais nous ne pouvons pas y insérer la carte mémoire. La carte ne peut pas être branchée à l'ordinateur, nous ne pouvons donc pas enregistrer nos photos, vidéos et autres données. Un lecteur de carte est un adaptateur qui résout ce problème. Après tout, il a un câble USB ! Contrairement à la carte elle-même, le lecteur de carte peut être branché sur l'ordinateur. Ils partagent une interface commune avec l'ordinateur : USB. Voyons à quoi cela ressemble en pratique:

public interface USB { 

   void connectWithUsbCable(); 
}
Il s'agit de notre interface USB avec une seule méthode de connexion via USB.

public class MemoryCard { 

   public void insert() { 
       System.out.println("Memory card successfully inserted!"); 
   } 

   public void copyData() { 
       System.out.println("The data has been copied to the computer!"); 
   } 
}
Ceci est notre classe représentant la carte mémoire. Il a déjà les 2 méthodes dont nous avons besoin, mais voici le problème : il n'implémente pas l'interface USB. La carte ne peut pas être insérée dans le port USB.

public class CardReader implements USB { 

   private MemoryCard memoryCard; 

   public CardReader(MemoryCard memoryCard) { 
       this.memoryCard = memoryCard; 
   } 

   @Override 
   public void connectWithUsbCable() { 
       this.memoryCard.insert(); 
       this.memoryCard.copyData(); 
   } 
}
Et voici notre adaptateur ! Que fait leCardReaderque fait la classe et qu'est-ce qui en fait exactement un adaptateur ? C'est tout simple. La classe en cours d'adaptation (MemoryCard) devient l'un des champs de l'adaptateur. C'est logique. Lorsque nous plaçons une carte mémoire dans un lecteur de carte dans la vraie vie, elle en fait également partie. Contrairement à la carte mémoire, l'adaptateur partage une interface avec l'ordinateur. Il dispose d'un câble USB, c'est-à-dire qu'il peut être connecté à d'autres appareils via USB. C'est pourquoi notre classe CardReader implémente l'interface USB. Mais que se passe-t-il exactement dans cette méthode ? Exactement ce dont nous avons besoin! L'adaptateur délègue le travail à notre carte mémoire. En effet, l'adaptateur ne fait rien lui-même. Un lecteur de carte n'a aucune fonctionnalité indépendante. Son travail consiste uniquement à connecter l'ordinateur et la carte mémoire afin de permettre à la carte de faire son travail - copier des fichiers !connectWithUsbCable()méthode) pour répondre aux "besoins" de la carte mémoire. Créons un programme client qui simulera une personne souhaitant copier des données depuis une carte mémoire :

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
Alors qu'avons-nous obtenu? Sortie console :

Memory card successfully inserted! 
The data has been copied to the computer!
Excellent. Nous avons atteint notre objectif ! Voici un lien vers une vidéo contenant des informations sur le modèle d'adaptateur :

Classes abstraites Reader et Writer

Nous allons maintenant revenir à notre activité préférée : apprendre quelques nouvelles classes pour travailler avec l'entrée et la sortie :) Je me demande combien nous en avons déjà appris. Aujourd'hui, nous allons parler des classes Reader et Writer. Pourquoi précisément ces cours ? Parce qu'ils sont liés à notre section précédente sur les adaptateurs. Examinons-les plus en détail. Nous allons commencer par  Reader. Readerest une classe abstraite, nous ne pourrons donc pas créer d'objets explicitement.   Mais vous le connaissez déjà ! Après tout, vous connaissez bien les classes BufferedReaderet InputStreamReader, qui en sont les descendantes :)

public class BufferedReader extends Reader { 
… 
} 

public class InputStreamReader extends Reader { 
… 
}
La InputStreamReaderclasse est un adaptateur classique. Comme vous vous en souvenez probablement, nous pouvons passer un InputStreamobjet à son constructeur. Pour ce faire, nous utilisons généralement la System.invariable :

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
Mais qu'est-ce que ça InputStreamReaderfait ? Comme tout adaptateur, il convertit une interface en une autre.  Dans ce cas, l' InputStreaminterface à l' Readerinterface. Au départ, nous avons la InputStreamclasse. Cela fonctionne bien, mais vous ne pouvez l'utiliser que pour lire des octets individuels. De plus, nous avons une Readerclasse abstraite. Il a des fonctionnalités très utiles - il sait lire les caractères ! Nous avons certainement besoin de cette capacité. Mais ici, nous sommes confrontés au problème classique généralement résolu par les adaptateurs - les interfaces incompatibles. Qu'est-ce que cela signifie? Jetons un coup d'œil à la documentation d'Oracle. Voici les méthodes de la InputStreamclasse. Modèle de conception d'adaptateur - 4Un ensemble de méthodes est précisément ce qu'est une interface. Comme vous pouvez le voir, cette classe a unread()méthode (quelques variantes, en fait), mais il ne peut lire que des octets : soit des octets individuels, soit plusieurs octets à l'aide d'un tampon. Mais cette option ne nous convient pas — nous voulons lire des caractères. Nous avons besoin de la fonctionnalité déjà implémentée dans la Readerclasse abstraite . Nous pouvons également le voir dans la documentation. Modèle de conception d'adaptateur - 5Cependant, les interfaces InputStreamet  Readersont incompatibles ! Comme vous pouvez le voir, chaque implémentation de la read()méthode a des paramètres et des valeurs de retour différents. Et c'est là qu'il nous faut InputStreamReader! Il servira d'adaptateur entre nos classes. Comme dans l'exemple avec le lecteur de carte, que nous avons considéré ci-dessus, nous plaçons une instance de la classe à adapter "à l'intérieur" de la classe adaptateur, c'est-à-dire que nous en passons une à son constructeur. Dans l'exemple précédent, nous avons mis un MemoryCardobjet à l'intérieur de CardReader. Nous passons maintenant un InputStream objet au InputStreamReaderconstructeur ! Nous utilisons notre System.invariable familière comme InputStream:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
Et en effet, en regardant la documentation de InputStreamReader, nous pouvons voir que l'adaptation a réussi :) Nous avons maintenant des méthodes pour lire les caractères à notre disposition. Modèle de conception d'adaptateur - 6Et bien que notre System.inobjet (le flux lié au clavier) ne le permette pas initialement, les créateurs du langage ont résolu ce problème en implémentant le modèle d'adaptateur. La Readerclasse abstraite, comme la plupart des classes d'E/S, a un frère jumeau —  Writer. Il a le même grand avantage que  Reader - il fournit une interface pratique pour travailler avec des personnages. Avec les flux de sortie, le problème et sa solution ressemblent à ceux des flux d'entrée. Il y a une OutputStreamclasse qui ne peut écrire que des octets, il y a unWriterclasse abstraite qui sait travailler avec des caractères, et il existe deux interfaces incompatibles. Ce problème est à nouveau résolu par le modèle d'adaptateur. Nous utilisons la OutputStreamWriterclasse pour adapter facilement les deux interfaces des classes Writer et  OutputStream entre elles. Après avoir passé un OutputStreamflux d'octets au constructeur, nous pouvons utiliser an OutputStreamWriterpour écrire des caractères plutôt que des octets !

import java.io.*; 

public class Main { 

   public static void main(String[] args) throws IOException { 

       OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt")); 
       streamWriter.write(32144); 
       streamWriter.close();
   } 
}
Nous avons écrit le caractère avec le code 32144 (綐) dans notre fichier, éliminant ainsi le besoin de travailler avec des octets :) C'est tout pour aujourd'hui. A bientôt dans les prochains cours ! :)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION