Patron Adaptateur
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 95 sur 110.
Le pattern Adapter permet à des interfaces incompatibles de travailler ensemble. Il agit comme un pont entre deux classes qui ne pourraient pas collaborer autrement, en enveloppant une classe existante avec une nouvelle interface attendue par les clients. Ceci est particulièrement utile lors de l'intégration de bibliothèques tierces ou de code hérité dans votre application.
Imaginez que vous ayez un système qui travaille avec des données JSON, mais que vous deviez intégrer un composant qui ne produit que du XML. Au lieu de modifier l'une ou l'autre classe, vous créez un adaptateur qui effectue la traduction entre les deux :
// Interface existante attendue par votre système
abstract class JsonData {
String getJson();
}
// Classe héritée avec une interface incompatible
class XmlService {
String getXml() {
return '<data><name>John</name></data>';
}
}
// L'adaptateur rend XmlService compatible avec JsonData
class XmlToJsonAdapter implements JsonData {
final XmlService _xmlService;
XmlToJsonAdapter(this._xmlService);
@override
String getJson() {
String xml = _xmlService.getXml();
// Convertir le XML en JSON (simplifié)
return '{"name": "John"}';
}
}
void main() {
var xmlService = XmlService();
var adapter = XmlToJsonAdapter(xmlService);
print(adapter.getJson()); // {"name": "John"}
}L'XmlToJsonAdapter enveloppe le XmlService et implémente l'interface JsonData. Le code client travaille avec l'interface familière JsonData sans savoir que les données provenaient initialement d'une source XML. L'adaptateur gère toute la traduction en interne.
Utilisez le patron Adaptateur lorsque vous souhaitez utiliser une classe existante mais que son interface ne correspond pas à ce dont vous avez besoin, ou lorsque vous devez créer une classe réutilisable qui coopère avec des classes ayant des interfaces incompatibles.
Défi
FacileConstruisons un système d'adaptateur de lecteur multimédia ! Imaginez que vous avez un système audio moderne qui s'attend à ce que toutes les sources multimédias fournissent de l'audio via une interface standard, mais vous devez intégrer un vieux tourne-disque vinyle qui a une manière complètement différente de produire du son.
Vous allez créer deux fichiers pour organiser votre implémentation du pattern adapter :
media_adapter.dart: Ce fichier contient votre interface et vos classes d'adaptateur. Définissez une classe abstraiteAudioSourceque votre système moderne attend - elle doit avoir une méthodeString playAudio()qui retourne la sortie audio sous forme de chaîne de caractères. Créez ensuite une classeVinylPlayerreprésentant l'équipement hérité - elle possède un champtrackNameet une méthodeString spinRecord()qui retourne*crackle* Playing vinyl: [trackName] *crackle*. Enfin, construisez unVinylAdapterqui implémenteAudioSourceet enveloppe unVinylPlayer. La méthodeplayAudio()de l'adaptateur doit appeler la méthodespinRecord()du lecteur vinyle et retourner le résultat - comblant ainsi le fossé entre les interfaces incompatibles.main.dart: Importez votre fichier d'adaptateur multimédia et démontrez comment l'adaptateur permet au vieux lecteur vinyle de fonctionner avec du code qui attend l'interface moderneAudioSource. Créez unVinylPlayeravec le nom de pisteBohemian Rhapsody. Créez ensuite unVinylAdapterqui enveloppe ce lecteur vinyle. Stockez l'adaptateur dans une variable de typeAudioSourcepour prouver qu'il se conforme à l'interface attendue. AppelezplayAudio()sur votre source audio et affichez le résultat.
La beauté de ce pattern est que votre code principal travaille avec l'interface standard AudioSource - il n'a pas besoin de savoir qu'en coulisses, un vieux lecteur vinyle fait le travail réel !
Sortie attendue :
*crackle* Playing vinyl: Bohemian Rhapsody *crackle*Aide-mémoire
Le pattern Adapter (ou Adaptateur) permet à des interfaces incompatibles de travailler ensemble en agissant comme un pont entre deux classes qui ne pourraient pas collaborer autrement.
L'adaptateur enveloppe une classe existante avec une nouvelle interface attendue par les clients, ce qui le rend utile lors de l'intégration de bibliothèques tierces ou de code hérité.
Structure de base
// Interface cible attendue par les clients
abstract class JsonData {
String getJson();
}
// Classe existante avec une interface incompatible
class XmlService {
String getXml() {
return '<data><name>John</name></data>';
}
}
// L'adaptateur rend XmlService compatible avec JsonData
class XmlToJsonAdapter implements JsonData {
final XmlService _xmlService;
XmlToJsonAdapter(this._xmlService);
@override
String getJson() {
String xml = _xmlService.getXml();
// Convertir le XML en JSON
return '{"name": "John"}';
}
}Utilisation
void main() {
var xmlService = XmlService();
var adapter = XmlToJsonAdapter(xmlService);
print(adapter.getJson()); // {"name": "John"}
}L'adaptateur implémente l'interface cible tout en enveloppant la classe incompatible. Le code client utilise l'interface familière sans connaître l'implémentation sous-jacente.
Quand l'utiliser : Lorsque vous devez utiliser une classe existante mais que son interface ne correspond pas à vos besoins, ou lors de la création d'une classe réutilisable qui coopère avec des classes ayant des interfaces incompatibles.
Essayez vous-même
import 'media_adapter.dart';
void main() {
// TODO: Créer un VinylPlayer avec le nom de piste "Bohemian Rhapsody"
// TODO: Créer un VinylAdapter qui enveloppe le lecteur vinyle
// TODO: Stocker l'adaptateur dans une variable de type AudioSource
// TODO: Appeler playAudio() sur votre source audio et imprimer le résultat
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository