Qual è il modello del ponte?
Il modello a ponte è un modello di progettazione strutturale. In altre parole, il suo compito principale è creare una struttura completa di classi e oggetti. Un bridge lo fa dividendo una o più classi in gerarchie separate: astrazione e implementazione . Un cambiamento di funzionalità in una gerarchia non comporta un cambiamento nell'altra. Va tutto bene, ma questa definizione è molto ampia e non risponde alla domanda più importante: "Qual è lo schema del ponte?" Penso che sarà più facile per te capire la sua applicazione pratica. Quindi, subito, creiamo uno scenario classico per il modello del ponte. Abbiamo unaShape
classe astratta, che rappresenta una figura geometrica generica:
-
Forma.java
public abstract class Shape { public abstract void draw(); }
Quando decidiamo di aggiungere forme come triangoli e rettangoli, faremo ereditare loro la
Shape
classe: -
Rettangolo.java:
public class Rectangle extends Shape { @Override public void draw() { System.out.println("Drawing rectangle"); } }
-
Triangolo.java:
public class Triangle extends Shape { @Override public void draw() { System.out.println("Drawing triangle"); } }
draw()
metodo dipenderà da questo colore. Per avere diverse implementazioni del draw()
metodo, allora dobbiamo creare una classe per ogni combinazione forma-colore. Se abbiamo tre colori, abbiamo bisogno di sei classi : TriangleBlack
, TriangleGreen
, TriangleRed
, e . Sei lezioni non sono un grosso problema. Ma! Se dobbiamo aggiungere una nuova forma o colore, il numero di classi cresce in modo esponenziale. Come uscire da questa situazione? Memorizzare il colore in un campo ed enumerare tutte le opzioni utilizzando istruzioni condizionali non è la soluzione migliore. Una buona soluzione è spostare il colore su un'interfaccia separataRectangleBlack
RectangleGreen
RectangleRed
. Detto fatto: creiamo un'interfaccia Color
con tre implementazioni: BlackColor
, GreenColor
e RedColor
:
-
Colore.java:
public interface Color { void fillColor(); }
-
BlackColor.java:
public class BlackColor implements Color { @Override public void fillColor() { System.out.println("Filling in black color"); } }
-
GreenColor.java
public class GreenColor implements Color { @Override public void fillColor() { System.out.println("Filling in green color"); } }
-
RedColor.java
public class RedColor implements Color { @Override public void fillColor() { System.out.println("Filling in red color"); } }
Ora aggiungiamo un
Color
campo allaShape
classe. Otterremo il suo valore nel costruttore. -
Shape.java:
public abstract class Shape { protected Color color; public Shape(Color color) { this.color = color; } public abstract void draw(); }
Useremo la
color
variabile nelleShape
implementazioni. Ciò significa che le forme possono ora utilizzare la funzionalità dell'interfacciaColor
. -
Rectangle.java
public class Rectangle extends Shape { public Rectangle(Color color) { super(color); } @Override public void draw() { System.out.println("Drawing rectangle"); color.fillColor(); } }
Color color
campo è un ponte che collega due gerarchie di classi separate.
Come costruire un ponte: astrazione e implementazione
Diamo un'occhiata a un diagramma di classe che rappresenta il pattern bridge: Qui puoi vedere due strutture indipendenti che possono essere modificate senza influire sulla funzionalità l'una dell'altra. Nel nostro caso:- L'astrazione è la
Shape
classe - RefinedAbstraction sono le classi
Triangle
eRectangle
- L'implementatore è l'
Color
interfaccia - ConcreteImplementor è il
BlackColor
,GreenColor
eRedColor
le classi.
Shape
classe è un'astrazione — un meccanismo per gestire il riempimento delle forme con vari colori, che delega all'interfaccia Color
(Implementor). Le classi Triangle
e Rectangle
sono classi concrete che utilizzano il meccanismo messo a disposizione dalla Shape
classe. BlackColor
e GreenColor
sono RedColor
implementazioni concrete nella gerarchia di implementazione.
Dove usare il motivo a ponte
Un enorme vantaggio dell'utilizzo di questo modello è che è possibile apportare modifiche alle classi funzionali in una gerarchia senza interrompere la logica dell'altra. Inoltre, questo approccio aiuta a ridurre l'accoppiamento tra le classi. Il requisito principale quando si utilizza questo modello è "seguire le istruzioni": non ignorarne nessuno! A tal fine, cerchiamo di capire le situazioni in cui dovresti assolutamente usare il pattern bridge:-
Se hai bisogno di espandere il numero di entità basate su combinazioni di due concetti (es. forme e colori).
-
Se si desidera dividere una classe numerosa che non soddisfa il principio della responsabilità singola in classi più piccole con funzionalità limitate.
-
Se è necessario apportare modifiche alla logica di alcune entità mentre il programma è in esecuzione.
-
Se è necessario nascondere un'implementazione ai client della classe o della libreria.
Pro e contro del modello
Come altri modelli, un ponte presenta sia vantaggi che svantaggi. Vantaggi del modello a ponte:- Migliora la scalabilità del codice: puoi aggiungere funzionalità senza timore di rompere qualcosa in un'altra parte del programma.
- Riduce il numero di sottoclassi quando il numero di entità sarebbe altrimenti basato su combinazioni di due concetti (ad esempio, forme e colori).
- Consente di lavorare separatamente su due gerarchie separate: astrazione e implementazione. Due diversi sviluppatori possono apportare modifiche senza approfondire i dettagli del codice dell'altro.
- Riduce l'accoppiamento tra classi: l'unico posto in cui le due classi sono accoppiate è il bridge (cioè il
Color color
campo).
- A seconda della situazione specifica e della struttura complessiva di un progetto, potrebbe influire negativamente sulle prestazioni di un programma (ad esempio, se è necessario inizializzare più oggetti).
- Rende il codice meno leggibile a causa della necessità di passare da una classe all'altra.
GO TO FULL VERSION