Bridge Pattern | Structural Design Pattern
Bridge Pattern
The Bridge Pattern is a structural design pattern that separates abstraction from implementation. It allows both to evolve independently without the need to modify each other. This pattern is particularly useful when you want to avoid a permanent binding between an abstraction and its implementation.
Here are the key components of the Bridge Pattern:
Abstraction: Defines the abstraction's interface and maintains a reference to an object of type Implementor.
Refined Abstraction: Extends the abstraction and adds finer details.
Implementor: Defines the interface for implementation classes. It doesn't have to correspond directly to the abstraction's interface.
Concrete Implementor: Implements the Implementor interface and defines its concrete implementation.
This pattern is beneficial when there are multiple dimensions of variability, and you want to avoid a Cartesian product of variations. It promotes flexibility and extensibility by allowing the abstraction and implementation to vary independently.
Here's a simple analogy using a drawing application:
Abstraction: Represents a shape in the drawing.
Refined Abstraction: Adds specific details to the shape, like color or border style.
Implementor: Defines drawing methods, such as drawing on a canvas.
Concrete Implementor: Implements the drawing methods for a specific rendering engine, like OpenGL or DirectX.
This way, we can have different shapes with various details drawn on different platforms without having to create a specific class for each combination.
Example of the Bridge Pattern in C# using a drawing application.
We'll have shapes (abstraction) that can be drawn using different rendering engines (implementation).
______
using System;
// Implementor interface
public interface IDrawingImplementor
{
void DrawCircle(int radius, int x, int y);
void DrawRectangle(int width, int height, int x, int y);
}
// Concrete Implementor 1
public class OpenGLDrawing : IDrawingImplementor
{
public void DrawCircle(int radius, int x, int y)
{
Console.WriteLine($"Drawing Circle in OpenGL at ({x}, {y}) with radius {radius}");
}
public void DrawRectangle(int width, int height, int x, int y)
{
Console.WriteLine($"Drawing Rectangle in OpenGL at ({x}, {y}) with width {width} and height {height}");
}
}
// Concrete Implementor 2
public class DirectXDrawing : IDrawingImplementor
{
public void DrawCircle(int radius, int x, int y)
{
Console.WriteLine($"Drawing Circle in DirectX at ({x}, {y}) with radius {radius}");
}
public void DrawRectangle(int width, int height, int x, int y)
{
Console.WriteLine($"Drawing Rectangle in DirectX at ({x}, {y}) with width {width} and height {height}");
}
}
// Abstraction
public abstract class Shape
{
protected IDrawingImplementor drawingImplementor;
protected Shape(IDrawingImplementor drawingImplementor)
{
this.drawingImplementor = drawingImplementor;
}
public abstract void Draw();
}
// Refined Abstraction 1
public class Circle : Shape
{
private int radius;
private int x;
private int y;
public Circle(IDrawingImplementor drawingImplementor, int radius, int x, int y)
: base(drawingImplementor)
{
this.radius = radius;
this.x = x;
this.y = y;
}
public override void Draw()
{
drawingImplementor.DrawCircle(radius, x, y);
}
}
// Refined Abstraction 2
public class Rectangle : Shape
{
private int width;
private int height;
private int x;
private int y;
public Rectangle(IDrawingImplementor drawingImplementor, int width, int height, int x, int y)
: base(drawingImplementor)
{
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
public override void Draw()
{
drawingImplementor.DrawRectangle(width, height, x, y);
}
}
class Program
{
static void Main()
{
// Using OpenGL for drawing
IDrawingImplementor openGLDrawing = new OpenGLDrawing();
Shape circle = new Circle(openGLDrawing, 5, 10, 20);
Shape rectangle = new Rectangle(openGLDrawing, 8, 6, 15, 25);
circle.Draw();
rectangle.Draw();
// Using DirectX for drawing
IDrawingImplementor directXDrawing = new DirectXDrawing();
circle = new Circle(directXDrawing, 3, 30, 40);
rectangle = new Rectangle(directXDrawing, 10, 7, 35, 45);
circle.Draw();
rectangle.Draw();
}
}
______
______
using System;
// Implementor interface
public interface IDevice
{
void TurnOn();
void TurnOff();
void SetChannel(int channel);
}
// Concrete Implementor 1
public class TV : IDevice
{
private bool isOn = false;
private int currentChannel = 0;
public void TurnOn()
{
isOn = true;
Console.WriteLine("TV is ON");
}
public void TurnOff()
{
isOn = false;
Console.WriteLine("TV is OFF");
}
public void SetChannel(int channel)
{
if (isOn)
{
currentChannel = channel;
Console.WriteLine($"Set TV channel to {channel}");
}
else
{
Console.WriteLine("TV is OFF. Please turn it on first.");
}
}
}
// Concrete Implementor 2
public class Radio : IDevice
{
private bool isOn = false;
private int currentChannel = 0;
public void TurnOn()
{
isOn = true;
Console.WriteLine("Radio is ON");
}
public void TurnOff()
{
isOn = false;
Console.WriteLine("Radio is OFF");
}
public void SetChannel(int channel)
{
if (isOn)
{
currentChannel = channel;
Console.WriteLine($"Set Radio channel to {channel}");
}
else
{
Console.WriteLine("Radio is OFF. Please turn it on first.");
}
}
}
// Abstraction
public abstract class RemoteControl
{
protected IDevice device;
protected RemoteControl(IDevice device)
{
this.device = device;
}
public abstract void TurnOn();
public abstract void TurnOff();
public abstract void SetChannel(int channel);
}
// Refined Abstraction 1
public class BasicRemoteControl : RemoteControl
{
public BasicRemoteControl(IDevice device)
: base(device)
{
}
public override void TurnOn()
{
device.TurnOn();
}
public override void TurnOff()
{
device.TurnOff();
}
public override void SetChannel(int channel)
{
device.SetChannel(channel);
}
}
// Refined Abstraction 2
public class AdvancedRemoteControl : RemoteControl
{
public AdvancedRemoteControl(IDevice device)
: base(device)
{
}
public void Mute()
{
Console.WriteLine("Muting the device");
}
}
class Program
{
static void Main()
{
// Using TV with a basic remote control
IDevice tv = new TV();
RemoteControl basicRemote = new BasicRemoteControl(tv);
basicRemote.TurnOn();
basicRemote.SetChannel(5);
basicRemote.TurnOff();
// Using Radio with an advanced remote control
IDevice radio = new Radio();
AdvancedRemoteControl advancedRemote = new AdvancedRemoteControl(radio);
advancedRemote.TurnOn();
advancedRemote.SetChannel(101);
advancedRemote.Mute();
advancedRemote.TurnOff();
}
}
______
Comments
Post a Comment