Quelle est la différence entre les modèles Bridge et Adapter?
"Adapter fait fonctionner les choses après leur conception; Bridge les fait Travailler avant qu'elles ne le soient. [GoF, p219]"
Effectivement, le modèle Adapter est utile lorsque vous avez un code existant, qu'il soit tiers ou interne, mais que vous ne le contrôlez pas, ou que vous ne pouvez pas le modifier pour qu'il corresponde parfaitement à l'interface dont vous avez besoin. Par exemple, nous avons un SuperWeaponsArray qui peut contrôler une gamme étendue de périphériques Doomsday.
public class SuperWeaponsArray {
/*...*/
public void destroyWorld() {
for (Weapon w : armedWeapons) {
w.fire();
}
}
}
Génial. Sauf que nous nous rendons compte que nous avons dans notre arsenal un dispositif nucléaire qui précède de loin la conversion à l'interface Weapon. Mais nous aimerions vraiment que cela fonctionne ici ... alors, que faisons-nous ... coincons-le!
NukeWeaponsAdaptor - basé sur notre classe Nuke, mais exportant l'interface Weapon. Doux, maintenant nous pouvons sûrement détruire le monde. Cela ressemble un peu à un kludge, mais cela fait fonctionner les choses.
Le modèle Bridge est quelque chose que vous implémentez dès le départ. Si vous savez que vous avez deux hiérarchies orthogonales, cela permet de découpler l'interface et l'implémentation de manière à ne pas obtenir un nombre insensé de classes. Disons que vous avez:
Types d’objets de fichier MemoryMappedFile et DirectReadFile. Supposons que vous souhaitiez pouvoir lire des fichiers provenant de différentes sources (peut-être des implémentations Linux ou Windows, etc.). Bridge vous aide à éviter de vous retrouver avec:
MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile
http://en.wikipedia.org/wiki/Adapter_pattern
Le modèle Adapter consiste davantage à faire en sorte que votre code existant fonctionne avec un système ou une interface plus récents.
Si vous souhaitez proposer un ensemble d'API de service Web standard de l'entreprise à l'interface d'extensibilité existante d'une autre application, vous pouvez envisager d'écrire un ensemble d'adaptateurs à cette fin. Notez qu'il existe une zone grise et qu'il s'agit davantage de la façon technique dont vous définissez le motif, car d'autres modèles, comme la façade, sont similaires.
http://en.wikipedia.org/wiki/Bridge_pattern
Le modèle Bridge va vous permettre d’avoir éventuellement des implémentations alternatives d’un algorithme ou d’un système.
Bien que ce ne soit pas un exemple classique de modèle Bridge, imaginez si vous aviez quelques implémentations d’un magasin de données: l’un est efficace en termes d’espace, l’autre en termes de performances brutes ... et vous avez une analyse de rentabilisation à offrir à la fois dans votre application ou votre infrastructure .
En ce qui concerne votre question, "Où puis-je utiliser quel modèle", la réponse est, où que ce soit logique pour votre projet! Envisagez peut-être de proposer une modification de clarification pour guider la discussion sur les domaines dans lesquels vous estimez avoir besoin d'utiliser l'un ou l'autre.
Adaptateur:
Diagramme UML: from dofactory article:
Target: définit l'interface spécifique au domaine utilisée par le client.
Adaptateur: adapte l'interface Adaptee à l'interface cible.
Adaptee: définit une interface existante à adapter.
Client: collabore avec des objets conformes à l'interface cible.
Exemple:
Carré et Rectangle sont deux formes différentes et obtenir une zone () de chacune d’elles nécessite des méthodes différentes. Mais toujours Square travaille sur l'interface Rectangle avec la conversion de certaines propriétés.
public class AdapterDemo{
public static void main(String args[]){
SquareArea s = new SquareArea(4);
System.out.println("Square area :"+s.getArea());
}
}
class RectangleArea {
public int getArea(int length, int width){
return length * width;
}
}
class SquareArea extends RectangleArea {
int length;
public SquareArea(int length){
this.length = length;
}
public int getArea(){
return getArea(length,length);
}
}
Bridge:
EDIT: (selon la suggestion de @quasoft)
Vous avez quatre composants dans ce modèle.
Abstraction: Définit une interface
RefinedAbstraction: Il implémente l'abstraction:
Implementor: définit une interface pour l'implémentation
ConcreteImplementor: Implémente l'interface Implementor.
Extrait de code:
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
Article similaire:
Quand utilisez-vous le modèle de pont? En quoi est-ce différent du motif adaptateur?
Principales différences: from sourcemaking article
Ce message existe depuis assez longtemps. Cependant, il est important de comprendre qu'une façade ressemble à un adaptateur, mais ce n'est pas tout à fait la même chose. Un adaptateur "adapte" une classe existante à une classe client généralement non compatible. Supposons que votre application utilise un ancien système de flux de travail en tant que client. Votre entreprise pourrait éventuellement remplacer le système de flux de travail par un nouveau système "incompatible" (en termes d'interfaces). Dans la plupart des cas, vous pouvez utiliser le modèle d'adaptateur et écrire du code qui appelle en réalité les interfaces du nouveau moteur de flux de travail. Un pont est généralement utilisé d'une manière différente. Si vous avez un système devant fonctionner avec différents systèmes de fichiers (disque local, NFS, etc.), vous pouvez utiliser le modèle de pont et créer une couche d’abstraction qui fonctionne avec tous vos systèmes de fichiers. Ce serait fondamentalement un cas d'utilisation simple pour le modèle de pont. La façade et l'adaptateur partagent certaines propriétés, mais les façades sont généralement utilisées pour simplifier une interface/classe existante . Au début des EJB, il n'y avait pas d'appel local pour les EJB. Les développeurs ont toujours obtenu le talon, l'ont réduit et appelé "pseudo-distant". Cela entraînait souvent des problèmes de performances (surtout quand on appelait vraiment par le fil). Les développeurs expérimentés utiliseraient le motif de façade pour fournir une interface très grossière au client. Cette façade ferait alors à son tour plusieurs appels à différentes méthodes plus détaillées. Au total, cela a considérablement réduit le nombre d'appels de méthode requis et a amélioré les performances.
Bridge est amélioré Adaptateur. Bridge comprend un adaptateur et ajoute une flexibilité supplémentaire. Voici comment les éléments de la réponse de Ravindra mappent entre les motifs:
Adapter | Bridge
-----------|---------------
Target | Abstraction
-----------|---------------
| RefinedAbstraction
|
| This element is Bridge specific. If there is a group of
| implementations that share the same logic, the logic can be placed here.
| For example, all cars split into two large groups: manual and auto.
| So, there will be two RefinedAbstraction classes.
-----------|---------------
Adapter | Implementor
-----------|---------------
Adaptee | ConcreteImplementor
Supposons que vous ayez une classe Shape abstraite avec une fonctionnalité de dessin (générique/abstraite) et un cercle qui implémente la forme. Le modèle de pont est simplement une approche d'abstraction bidirectionnelle pour découpler la mise en œuvre (dessin dans Circle) et la fonctionnalité générique/abstraite (dessin dans la classe Shape).
Qu'est-ce que cela signifie vraiment? À première vue, cela ressemble à quelque chose que vous faites déjà (par inversion de dépendance). Donc, ne vous inquiétez pas d'avoir une base de code moins évolutive ou plus modulaire. Mais c'est une philosophie un peu plus profonde derrière cela.
De mon point de vue, le besoin de modèle d'utilisation peut apparaître lorsque je dois ajouter de nouvelles classes qui sont étroitement liées au système actuel (comme RedCircle ou GreenCircle) et qui ne diffèrent que par une seule fonctionnalité (comme la couleur). Et je vais avoir besoin du motif Bridge, en particulier si les classes système existantes (Circle ou Shape) doivent être fréquemment modifiées et si vous ne souhaitez pas que les classes nouvellement ajoutées soient affectées par ces modifications. C'est pourquoi la fonctionnalité de dessin générique est abstraite dans une nouvelle interface, ce qui vous permet de modifier le comportement du dessin indépendamment de Shape ou Circle.