El patrón Bridge separa una abstracción de su implementación para que ambas evolucionen por separado.
1. El Problema de Partida
El proyecto muestra distintos tipos de visualización (BarChart, LineChart) y podría necesitar renderizarlos con librerías distintas según contexto (Recharts en cliente, un renderer estático SVG en build time para el OG image). Sin Bridge, tendríamos BarChartRecharts, BarChartStaticSVG, LineChartRecharts, LineChartStaticSVG... una subclase por cada combinación tipo × librería.
2. La Solución Bridge
// src/lib/charts/ChartRenderer.js — Implementador
export class ChartRenderer {
renderBars(data) { throw new Error('No implementado'); }
}
export class RechartsRenderer extends ChartRenderer {
renderBars(data) {
return <RechartsBarChart data={data} />; // Componente interactivo cliente
}
}
export class StaticSvgRenderer extends ChartRenderer {
renderBars(data) {
// Genera SVG plano, útil para exportar como imagen OG
return data.map((d, i) => `<rect x="${i * 20}" height="${d.value}" />`).join('');
}
}// src/components/dataviz/Chart.jsx — Abstracción
export default function Chart({ data, renderer }) {
return <div className="chart-container">{renderer.renderBars(data)}</div>;
}3. Uso
// En la página normal (interactivo)
<Chart data={salesData} renderer={new RechartsRenderer()} />
// En la generación de imagen OG (estático, sin JS de cliente)
<Chart data={salesData} renderer={new StaticSvgRenderer()} />4. Ventajas
- Sin explosión de componentes: un único
Chartcombina cualquier tipo de dato con cualquier renderer. - Cambiar de librería de charting solo implica escribir un nuevo
ChartRenderer, sin tocar los componentes que consumenChart. - Testeable de forma aislada: se puede probar la lógica del renderer sin montar todo el árbol de React.