Another example could involve a logging framework that supports multiple logging destinations (e.g., file, database, console) while keeping the logging logic independent of these implementations.
Implementor Interface:
// Implementor interface
public interface ILoggerImplementor
{
void Log(string message);
}
Concrete Implementors:
// Concrete Implementor 1: File logger
public class FileLogger : ILoggerImplementor
{
public void Log(string message)
{
Console.WriteLine($"Logging to file: {message}");
}
}
// Concrete Implementor 2: Database logger
public class DatabaseLogger : ILoggerImplementor
{
public void Log(string message)
{
Console.WriteLine($"Logging to database: {message}");
}
}
Abstraction:
// Abstraction
public abstract class Logger
{
protected ILoggerImplementor implementor;
protected Logger(ILoggerImplementor implementor)
{
this.implementor = implementor;
}
public abstract void Log(string message);
}
Refined Abstractions:
// Refined Abstraction 1: Error logger
public class ErrorLogger : Logger
{
public ErrorLogger(ILoggerImplementor implementor) : base(implementor)
{
}
public override void Log(string message)
{
implementor.Log($"[ERROR] {message}");
}
}
Client Code:
class Program
{
static void Main(string[] args)
{
// Create loggers with different implementations
Logger errorLogger1 = new ErrorLogger(new FileLogger());
Logger errorLogger2 = new ErrorLogger(new DatabaseLogger());
// Log messages
errorLogger1.Log("Failed to connect to server");
errorLogger2.Log("Database connection timeout");
}
}
In conclusion, the Bridge pattern is a powerful design pattern that facilitates flexibility, extensibility, and maintainability in software systems by decoupling abstraction from implementation. By using composition rather than inheritance, it allows both abstraction and implementation to vary independently, accommodating changes and extensions more easily. Bridge pattern promotes good software design practices by promoting separation of concerns and modular development, making it an essential tool in the toolkit of any software architect or developer aiming for scalable and maintainable systems.