Design Pattern 12: Bridge Pattern - Complete Guide with Real-World Security System Examples

πŸ“ Download the complete Design Pattern series code from our design_pattern repository.


🎯 What is the Bridge Pattern?

The Bridge Pattern is a structural design pattern that decouples an abstraction from its implementation, allowing both to vary independently. It provides a bridge between the abstraction and implementation, enabling you to change either without affecting the other.

Key Benefits:

  • βœ… Decoupling - Separate abstraction from implementation
  • βœ… Extensibility - Add new abstractions and implementations independently
  • βœ… Flexibility - Mix and match abstractions with implementations
  • βœ… Maintainability - Changes to one don’t affect the other
  • βœ… Open/Closed Principle - Open for extension, closed for modification

πŸš€ Real-World Problem: Security System with Multiple Notification Methods

Let’s design a security system with the following requirements:

System Requirements:

  • Multiple alarm types (Fire, Burglar, Environmental, Medical)
  • Various notification methods (APNS, FCM, Email, SMS, Slack)
  • Flexible combinations - any alarm type with any notification method
  • Easy extension - add new alarm types or notification methods
  • High performance - handle multiple concurrent alarms

Business Rules:

  • Each alarm type has specific message formatting and priority
  • Different notification methods have different delivery characteristics
  • System should support dynamic alarm-notification combinations
  • New alarm types or notification methods should be easy to add
  • System should handle notification failures gracefully

πŸ—οΈ Object-Oriented Analysis (OOA)

Let’s analyze the problem and identify the core components:

Identified Forces:

  1. Class Explosion
    • Creating a class for every alarm-notification combination leads to exponential growth
    • Maintenance becomes difficult with many classes
    • Code duplication across similar combinations
  2. Tight Coupling
    • Alarm types and notification methods are tightly coupled
    • Changes to one affect multiple classes
    • Difficult to add new alarm types or notification methods
  3. Inflexible Design
    • Cannot dynamically change notification methods
    • Hard to test individual components
    • Limited reusability

πŸ’‘ Bridge Pattern Solution

After analyzing the forces, we can apply the Bridge Pattern to create a flexible, decoupled system:

Bridge Pattern Components:

  1. Abstraction - Defines the interface for the abstraction
  2. Refined Abstraction - Extends the abstraction with specific functionality
  3. Implementor - Defines the interface for the implementation
  4. Concrete Implementor - Implements the implementor interface

Benefits:

  • Decoupled design - Abstraction and implementation vary independently
  • Flexible combinations - Mix and match abstractions with implementations
  • Easy extension - Add new abstractions or implementations without affecting existing code
  • Better testing - Test abstractions and implementations separately

πŸ› οΈ Implementation: Security System with Multiple Notification Methods

1. Implementor Interface (Notification Methods)

interface MessageSender {
    fun sendMessage(message: String, priority: Priority): SendResult
    fun getSupportedPriorities(): List<Priority>
    fun getDeliveryTime(): Long
    fun isAvailable(): Boolean
}

enum class Priority {
    LOW, MEDIUM, HIGH, CRITICAL
}

data class SendResult(
    val success: Boolean,
    val messageId: String? = null,
    val deliveryTime: Long = 0,
    val error: String? = null
)

2. Concrete Implementors (Notification Methods)

class APNSSender : MessageSender {
    private var isConnected = true
    
    override fun sendMessage(message: String, priority: Priority): SendResult {
        if (!isAvailable()) {
            return SendResult(false, error = "APNS not available")
        }
        
        val deliveryTime = getDeliveryTime()
        val messageId = "apns_${System.currentTimeMillis()}"
        
        println("πŸ“± APNS: Sending message (Priority: $priority)")
        println("   Message: $message")
        println("   Delivery Time: ${deliveryTime}ms")
        
        return SendResult(
            success = true,
            messageId = messageId,
            deliveryTime = deliveryTime
        )
    }
    
    override fun getSupportedPriorities(): List<Priority> = 
        listOf(Priority.LOW, Priority.MEDIUM, Priority.HIGH, Priority.CRITICAL)
    
    override fun getDeliveryTime(): Long = 100 // 100ms average delivery time
    
    override fun isAvailable(): Boolean = isConnected
    
    fun setConnectionStatus(connected: Boolean) {
        isConnected = connected
    }
}

class FCMSender : MessageSender {
    override fun sendMessage(message: String, priority: Priority): SendResult {
        val deliveryTime = getDeliveryTime()
        val messageId = "fcm_${System.currentTimeMillis()}"
        
        println("πŸ“² FCM: Sending message (Priority: $priority)")
        println("   Message: $message")
        println("   Delivery Time: ${deliveryTime}ms")
        
        return SendResult(
            success = true,
            messageId = messageId,
            deliveryTime = deliveryTime
        )
    }
    
    override fun getSupportedPriorities(): List<Priority> = 
        listOf(Priority.MEDIUM, Priority.HIGH, Priority.CRITICAL)
    
    override fun getDeliveryTime(): Long = 150 // 150ms average delivery time
    
    override fun isAvailable(): Boolean = true
}

class EmailSender : MessageSender {
    override fun sendMessage(message: String, priority: Priority): SendResult {
        val deliveryTime = getDeliveryTime()
        val messageId = "email_${System.currentTimeMillis()}"
        
        println("πŸ“§ Email: Sending message (Priority: $priority)")
        println("   Subject: [${priority.name}] Security Alert")
        println("   Body: $message")
        println("   Delivery Time: ${deliveryTime}ms")
        
        return SendResult(
            success = true,
            messageId = messageId,
            deliveryTime = deliveryTime
        )
    }
    
    override fun getSupportedPriorities(): List<Priority> = 
        listOf(Priority.LOW, Priority.MEDIUM, Priority.HIGH)
    
    override fun getDeliveryTime(): Long = 5000 // 5 seconds average delivery time
    
    override fun isAvailable(): Boolean = true
}

class SMSSender : MessageSender {
    override fun sendMessage(message: String, priority: Priority): SendResult {
        val deliveryTime = getDeliveryTime()
        val messageId = "sms_${System.currentTimeMillis()}"
        
        println("πŸ“± SMS: Sending message (Priority: $priority)")
        println("   Message: $message")
        println("   Delivery Time: ${deliveryTime}ms")
        
        return SendResult(
            success = true,
            messageId = messageId,
            deliveryTime = deliveryTime
        )
    }
    
    override fun getSupportedPriorities(): List<Priority> = 
        listOf(Priority.HIGH, Priority.CRITICAL)
    
    override fun getDeliveryTime(): Long = 2000 // 2 seconds average delivery time
    
    override fun isAvailable(): Boolean = true
}

class SlackSender : MessageSender {
    override fun sendMessage(message: String, priority: Priority): SendResult {
        val deliveryTime = getDeliveryTime()
        val messageId = "slack_${System.currentTimeMillis()}"
        
        val channel = when (priority) {
            Priority.CRITICAL -> "#security-critical"
            Priority.HIGH -> "#security-alerts"
            Priority.MEDIUM -> "#security-notifications"
            Priority.LOW -> "#security-info"
        }
        
        println("πŸ’¬ Slack: Sending message to $channel (Priority: $priority)")
        println("   Message: $message")
        println("   Delivery Time: ${deliveryTime}ms")
        
        return SendResult(
            success = true,
            messageId = messageId,
            deliveryTime = deliveryTime
        )
    }
    
    override fun getSupportedPriorities(): List<Priority> = 
        listOf(Priority.LOW, Priority.MEDIUM, Priority.HIGH, Priority.CRITICAL)
    
    override fun getDeliveryTime(): Long = 300 // 300ms average delivery time
    
    override fun isAvailable(): Boolean = true
}

3. Abstraction (Alarm Notifications)

abstract class AlarmNotification(
    protected val sender: MessageSender
) {
    abstract fun notifyUser(details: String, priority: Priority): SendResult
    abstract fun getAlarmType(): String
    abstract fun getDefaultPriority(): Priority
    
    fun isSenderCompatible(): Boolean {
        return sender.getSupportedPriorities().contains(getDefaultPriority())
    }
    
    fun getSenderInfo(): String {
        return "${sender::class.simpleName} (${sender.getDeliveryTime()}ms delivery)"
    }
}

4. Refined Abstractions (Specific Alarm Types)

class FireAlarmNotification(sender: MessageSender) : AlarmNotification(sender) {
    override fun notifyUser(details: String, priority: Priority): SendResult {
        val message = buildString {
            appendLine("πŸ”₯ FIRE ALARM ACTIVATED")
            appendLine("Location: $details")
            appendLine("Time: ${java.time.LocalDateTime.now()}")
            appendLine("Priority: $priority")
            appendLine("Action Required: Immediate evacuation")
        }
        
        return sender.sendMessage(message, priority)
    }
    
    override fun getAlarmType(): String = "Fire Alarm"
    
    override fun getDefaultPriority(): Priority = Priority.CRITICAL
}

class BurglarAlarmNotification(sender: MessageSender) : AlarmNotification(sender) {
    override fun notifyUser(details: String, priority: Priority): SendResult {
        val message = buildString {
            appendLine("🚨 BURGLAR ALARM ACTIVATED")
            appendLine("Location: $details")
            appendLine("Time: ${java.time.LocalDateTime.now()}")
            appendLine("Priority: $priority")
            appendLine("Action Required: Contact security immediately")
        }
        
        return sender.sendMessage(message, priority)
    }
    
    override fun getAlarmType(): String = "Burglar Alarm"
    
    override fun getDefaultPriority(): Priority = Priority.HIGH
}

class EnvironmentalAlarmNotification(sender: MessageSender) : AlarmNotification(sender) {
    override fun notifyUser(details: String, priority: Priority): SendResult {
        val message = buildString {
            appendLine("🌑️ ENVIRONMENTAL ALARM ACTIVATED")
            appendLine("Issue: $details")
            appendLine("Time: ${java.time.LocalDateTime.now()}")
            appendLine("Priority: $priority")
            appendLine("Action Required: Check environmental systems")
        }
        
        return sender.sendMessage(message, priority)
    }
    
    override fun getAlarmType(): String = "Environmental Alarm"
    
    override fun getDefaultPriority(): Priority = Priority.MEDIUM
}

class MedicalAlarmNotification(sender: MessageSender) : AlarmNotification(sender) {
    override fun notifyUser(details: String, priority: Priority): SendResult {
        val message = buildString {
            appendLine("πŸ₯ MEDICAL ALARM ACTIVATED")
            appendLine("Patient: $details")
            appendLine("Time: ${java.time.LocalDateTime.now()}")
            appendLine("Priority: $priority")
            appendLine("Action Required: Immediate medical attention")
        }
        
        return sender.sendMessage(message, priority)
    }
    
    override fun getAlarmType(): String = "Medical Alarm"
    
    override fun getDefaultPriority(): Priority = Priority.CRITICAL
}

5. Enhanced Security System with Multiple Notifications

class SecuritySystem {
    private val notifications = mutableListOf<AlarmNotification>()
    private val alarmHistory = mutableListOf<AlarmRecord>()
    
    fun addNotification(notification: AlarmNotification) {
        if (notification.isSenderCompatible()) {
            notifications.add(notification)
            println("βœ… Added ${notification.getAlarmType()} with ${notification.getSenderInfo()}")
        } else {
            println("❌ ${notification.getAlarmType()} not compatible with ${notification.getSenderInfo()}")
        }
    }
    
    fun triggerAlarm(alarmType: String, details: String, priority: Priority? = null) {
        println("\n🚨 Triggering $alarmType alarm...")
        println("Details: $details")
        
        val compatibleNotifications = notifications.filter { 
            it.getAlarmType() == alarmType 
        }
        
        if (compatibleNotifications.isEmpty()) {
            println("❌ No compatible notifications found for $alarmType")
            return
        }
        
        val results = mutableListOf<SendResult>()
        
        compatibleNotifications.forEach { notification ->
            val actualPriority = priority ?: notification.getDefaultPriority()
            println("\nπŸ“€ Sending via ${notification.getSenderInfo()}")
            
            val result = notification.notifyUser(details, actualPriority)
            results.add(result)
            
            if (result.success) {
                println("βœ… Notification sent successfully (ID: ${result.messageId})")
            } else {
                println("❌ Notification failed: ${result.error}")
            }
        }
        
        // Record alarm
        alarmHistory.add(AlarmRecord(
            alarmType = alarmType,
            details = details,
            priority = priority,
            timestamp = System.currentTimeMillis(),
            results = results
        ))
        
        println("\nπŸ“Š Alarm Summary:")
        println("- Total notifications sent: ${results.size}")
        println("- Successful: ${results.count { it.success }}")
        println("- Failed: ${results.count { !it.success }}")
    }
    
    fun getAlarmHistory(): List<AlarmRecord> = alarmHistory.toList()
    
    fun getNotificationStats(): Map<String, Int> {
        return notifications.groupBy { it.getAlarmType() }
            .mapValues { it.value.size }
    }
}

data class AlarmRecord(
    val alarmType: String,
    val details: String,
    val priority: Priority?,
    val timestamp: Long,
    val results: List<SendResult>
)

6. Client Code

fun main() {
    println("=== Security System Bridge Pattern Demo ===\n")
    
    val securitySystem = SecuritySystem()
    
    // Create different notification senders
    val apnsSender = APNSSender()
    val fcmSender = FCMSender()
    val emailSender = EmailSender()
    val smsSender = SMSSender()
    val slackSender = SlackSender()
    
    // Add different alarm-notification combinations
    println("πŸ”§ Setting up alarm notifications...")
    
    // Fire alarms with different notification methods
    securitySystem.addNotification(FireAlarmNotification(apnsSender))
    securitySystem.addNotification(FireAlarmNotification(emailSender))
    securitySystem.addNotification(FireAlarmNotification(slackSender))
    
    // Burglar alarms with different notification methods
    securitySystem.addNotification(BurglarAlarmNotification(fcmSender))
    securitySystem.addNotification(BurglarAlarmNotification(smsSender))
    securitySystem.addNotification(BurglarAlarmNotification(slackSender))
    
    // Environmental alarms
    securitySystem.addNotification(EnvironmentalAlarmNotification(emailSender))
    securitySystem.addNotification(EnvironmentalAlarmNotification(slackSender))
    
    // Medical alarms
    securitySystem.addNotification(MedicalAlarmNotification(apnsSender))
    securitySystem.addNotification(MedicalAlarmNotification(smsSender))
    
    println("\nπŸ“Š Notification Statistics:")
    securitySystem.getNotificationStats().forEach { (alarmType, count) ->
        println("   β€’ $alarmType: $count notification methods")
    }
    
    println("\n" + "=" * 60)
    
    // Trigger various alarms
    println("\nπŸ”₯ Triggering Fire Alarm...")
    securitySystem.triggerAlarm("Fire Alarm", "Building A, Floor 3", Priority.CRITICAL)
    
    println("\n🚨 Triggering Burglar Alarm...")
    securitySystem.triggerAlarm("Burglar Alarm", "Main Entrance", Priority.HIGH)
    
    println("\n🌑️ Triggering Environmental Alarm...")
    securitySystem.triggerAlarm("Environmental Alarm", "HVAC System Failure", Priority.MEDIUM)
    
    println("\nπŸ₯ Triggering Medical Alarm...")
    securitySystem.triggerAlarm("Medical Alarm", "Room 205 - Patient John Doe", Priority.CRITICAL)
    
    println("\n" + "=" * 60)
    
    // Demonstrate flexibility - change notification method at runtime
    println("\nπŸ”„ Demonstrating runtime flexibility...")
    
    // Add a new notification method for existing alarm type
    securitySystem.addNotification(FireAlarmNotification(fcmSender))
    
    // Trigger fire alarm again to see new notification method
    println("\nπŸ”₯ Triggering Fire Alarm with additional notification method...")
    securitySystem.triggerAlarm("Fire Alarm", "Building B, Floor 1", Priority.HIGH)
    
    println("\n" + "=" * 60)
    
    // Show alarm history
    println("\nπŸ“‹ Alarm History Summary:")
    securitySystem.getAlarmHistory().forEachIndexed { index, record ->
        println("${index + 1}. ${record.alarmType}")
        println("   Details: ${record.details}")
        println("   Priority: ${record.priority ?: "Default"}")
        println("   Time: ${java.time.Instant.ofEpochMilli(record.timestamp)}")
        println("   Results: ${record.results.count { it.success }}/${record.results.size} successful")
        println()
    }
}

Expected Output:

=== Security System Bridge Pattern Demo ===

πŸ”§ Setting up alarm notifications...
βœ… Added Fire Alarm with APNSSender (100ms delivery)
βœ… Added Fire Alarm with EmailSender (5000ms delivery)
βœ… Added Fire Alarm with SlackSender (300ms delivery)
βœ… Added Burglar Alarm with FCMSender (150ms delivery)
βœ… Added Burglar Alarm with SMSSender (2000ms delivery)
βœ… Added Burglar Alarm with SlackSender (300ms delivery)
βœ… Added Environmental Alarm with EmailSender (5000ms delivery)
βœ… Added Environmental Alarm with SlackSender (300ms delivery)
βœ… Added Medical Alarm with APNSSender (100ms delivery)
βœ… Added Medical Alarm with SMSSender (2000ms delivery)

πŸ“Š Notification Statistics:
   β€’ Fire Alarm: 3 notification methods
   β€’ Burglar Alarm: 3 notification methods
   β€’ Environmental Alarm: 2 notification methods
   β€’ Medical Alarm: 2 notification methods

============================================================

πŸ”₯ Triggering Fire Alarm...
🚨 Triggering Fire Alarm alarm...
Details: Building A, Floor 3

πŸ“€ Sending via APNSSender (100ms delivery)
πŸ“± APNS: Sending message (Priority: CRITICAL)
   Message: πŸ”₯ FIRE ALARM ACTIVATED
Location: Building A, Floor 3
Time: 2024-12-08T20:00:00
Priority: CRITICAL
Action Required: Immediate evacuation
   Delivery Time: 100ms
βœ… Notification sent successfully (ID: apns_1702044000000)

πŸ“€ Sending via EmailSender (5000ms delivery)
πŸ“§ Email: Sending message (Priority: CRITICAL)
   Subject: [CRITICAL] Security Alert
   Body: πŸ”₯ FIRE ALARM ACTIVATED
Location: Building A, Floor 3
Time: 2024-12-08T20:00:00
Priority: CRITICAL
Action Required: Immediate evacuation
   Delivery Time: 5000ms
βœ… Notification sent successfully (ID: email_1702044000001)

πŸ“€ Sending via SlackSender (300ms delivery)
πŸ’¬ Slack: Sending message to #security-critical (Priority: CRITICAL)
   Message: πŸ”₯ FIRE ALARM ACTIVATED
Location: Building A, Floor 3
Time: 2024-12-08T20:00:00
Priority: CRITICAL
Action Required: Immediate evacuation
   Delivery Time: 300ms
βœ… Notification sent successfully (ID: slack_1702044000002)

πŸ“Š Alarm Summary:
- Total notifications sent: 3
- Successful: 3
- Failed: 0

[... similar output for other alarms ...]

============================================================

πŸ“‹ Alarm History Summary:
1. Fire Alarm
   Details: Building A, Floor 3
   Priority: CRITICAL
   Time: 2024-12-08T20:00:00Z
   Results: 3/3 successful

2. Burglar Alarm
   Details: Main Entrance
   Priority: HIGH
   Time: 2024-12-08T20:00:01Z
   Results: 3/3 successful

[... more alarm history ...]

πŸ“Š Bridge Pattern vs Alternative Approaches

Approach Pros Cons
Bridge Pattern βœ… Decoupled design
βœ… Flexible combinations
βœ… Easy extension
❌ Increased complexity
❌ Additional abstraction layer
❌ Learning curve
Inheritance βœ… Simple for small hierarchies
βœ… Clear relationship
❌ Class explosion
❌ Tight coupling
❌ Hard to extend
Composition βœ… Reuse existing code
βœ… Flexible design
❌ No clear abstraction boundary
❌ Potential complexity
Strategy Pattern βœ… Runtime behavior switching
βœ… Clean separation
❌ Different purpose (behavior vs structure)

🎯 When to Use the Bridge Pattern

βœ… Perfect For:

  • Multiple implementations (different platforms, protocols, formats)
  • Runtime flexibility (change implementation at runtime)
  • Extensible systems (add new abstractions or implementations)
  • Platform independence (abstract platform-specific details)
  • Complex hierarchies (avoid class explosion)

❌ Avoid When:

  • Simple systems (overkill for basic requirements)
  • Static implementations (no need for runtime flexibility)
  • Performance-critical applications (abstraction overhead)
  • Tight coupling acceptable (when flexibility isn’t needed)

πŸ”§ Advanced Bridge Pattern Implementations

1. Bridge with Factory Pattern

class NotificationFactory {
    private val senders = mutableMapOf<String, MessageSender>()
    private val notifications = mutableMapOf<String, AlarmNotification>()
    
    fun registerSender(name: String, sender: MessageSender) {
        senders[name] = sender
        println("πŸ“ Registered sender: $name")
    }
    
    fun createNotification(alarmType: String, senderName: String): AlarmNotification? {
        val sender = senders[senderName] ?: return null
        
        return when (alarmType.lowercase()) {
            "fire" -> FireAlarmNotification(sender)
            "burglar" -> BurglarAlarmNotification(sender)
            "environmental" -> EnvironmentalAlarmNotification(sender)
            "medical" -> MedicalAlarmNotification(sender)
            else -> null
        }
    }
    
    fun getAvailableSenders(): List<String> = senders.keys.toList()
    
    fun getAvailableAlarmTypes(): List<String> = listOf("Fire", "Burglar", "Environmental", "Medical")
}

// Usage
val factory = NotificationFactory()
factory.registerSender("apns", APNSSender())
factory.registerSender("fcm", FCMSender())
factory.registerSender("email", EmailSender())

val fireNotification = factory.createNotification("Fire", "apns")
val burglarNotification = factory.createNotification("Burglar", "email")

2. Bridge with Configuration

class ConfigurableSecuritySystem(
    private val config: SecurityConfig
) {
    private val notifications = mutableListOf<AlarmNotification>()
    
    fun initialize() {
        config.getAlarmConfigurations().forEach { alarmConfig ->
            val sender = createSender(alarmConfig.senderType)
            val notification = createNotification(alarmConfig.alarmType, sender)
            
            if (notification != null) {
                notifications.add(notification)
                println("βœ… Configured ${alarmConfig.alarmType} with ${alarmConfig.senderType}")
            }
        }
    }
    
    private fun createSender(senderType: String): MessageSender {
        return when (senderType.lowercase()) {
            "apns" -> APNSSender()
            "fcm" -> FCMSender()
            "email" -> EmailSender()
            "sms" -> SMSSender()
            "slack" -> SlackSender()
            else -> throw IllegalArgumentException("Unknown sender type: $senderType")
        }
    }
    
    private fun createNotification(alarmType: String, sender: MessageSender): AlarmNotification? {
        return when (alarmType.lowercase()) {
            "fire" -> FireAlarmNotification(sender)
            "burglar" -> BurglarAlarmNotification(sender)
            "environmental" -> EnvironmentalAlarmNotification(sender)
            "medical" -> MedicalAlarmNotification(sender)
            else -> null
        }
    }
    
    fun triggerAlarm(alarmType: String, details: String) {
        val compatibleNotifications = notifications.filter { 
            it.getAlarmType() == alarmType 
        }
        
        compatibleNotifications.forEach { notification ->
            notification.notifyUser(details, notification.getDefaultPriority())
        }
    }
}

data class SecurityConfig(
    private val alarmConfigurations: List<AlarmConfiguration>
) {
    fun getAlarmConfigurations(): List<AlarmConfiguration> = alarmConfigurations
}

data class AlarmConfiguration(
    val alarmType: String,
    val senderType: String,
    val priority: Priority
)

3. Bridge with Monitoring and Metrics

class MonitoredSecuritySystem(
    private val securitySystem: SecuritySystem,
    private val monitor: SecurityMonitor
) {
    fun triggerAlarm(alarmType: String, details: String, priority: Priority? = null) {
        val startTime = System.currentTimeMillis()
        
        monitor.recordAlarmTrigger(alarmType, priority)
        
        try {
            securitySystem.triggerAlarm(alarmType, details, priority)
            monitor.recordAlarmSuccess(alarmType, System.currentTimeMillis() - startTime)
        } catch (e: Exception) {
            monitor.recordAlarmFailure(alarmType, e.message ?: "Unknown error")
            throw e
        }
    }
    
    fun getMetrics(): SecurityMetrics = monitor.getMetrics()
}

class SecurityMonitor {
    private val alarmTriggers = mutableMapOf<String, Int>()
    private val alarmSuccesses = mutableMapOf<String, Int>()
    private val alarmFailures = mutableMapOf<String, Int>()
    private val responseTimes = mutableMapOf<String, MutableList<Long>>()
    
    fun recordAlarmTrigger(alarmType: String, priority: Priority?) {
        alarmTriggers[alarmType] = (alarmTriggers[alarmType] ?: 0) + 1
        println("πŸ“Š Alarm triggered: $alarmType (Priority: ${priority ?: "Default"})")
    }
    
    fun recordAlarmSuccess(alarmType: String, responseTime: Long) {
        alarmSuccesses[alarmType] = (alarmSuccesses[alarmType] ?: 0) + 1
        responseTimes.getOrPut(alarmType) { mutableListOf() }.add(responseTime)
        println("βœ… Alarm success: $alarmType (${responseTime}ms)")
    }
    
    fun recordAlarmFailure(alarmType: String, error: String) {
        alarmFailures[alarmType] = (alarmFailures[alarmType] ?: 0) + 1
        println("❌ Alarm failure: $alarmType - $error")
    }
    
    fun getMetrics(): SecurityMetrics {
        return SecurityMetrics(
            alarmTriggers = alarmTriggers.toMap(),
            alarmSuccesses = alarmSuccesses.toMap(),
            alarmFailures = alarmFailures.toMap(),
            averageResponseTimes = responseTimes.mapValues { (_, times) ->
                times.average()
            }
        )
    }
}

data class SecurityMetrics(
    val alarmTriggers: Map<String, Int>,
    val alarmSuccesses: Map<String, Int>,
    val alarmFailures: Map<String, Int>,
    val averageResponseTimes: Map<String, Double>
)

πŸš€ Real-World Applications

1. Platform Abstraction

  • Cross-platform applications - Abstract platform-specific implementations
  • Database drivers - Different database implementations
  • Graphics rendering - Different rendering engines
  • Network protocols - Different communication protocols

2. Device Integration

  • Hardware abstraction - Different device implementations
  • Sensor systems - Different sensor types and protocols
  • IoT devices - Different IoT platform integrations
  • Payment systems - Different payment processor integrations

3. Framework Development

  • Plugin systems - Different plugin implementations
  • Middleware - Different middleware implementations
  • Caching systems - Different cache implementations
  • Logging systems - Different logging implementations

4. Enterprise Systems

  • Notification systems - Different notification channels
  • Authentication - Different authentication providers
  • File storage - Different storage backends
  • Message queues - Different queue implementations

πŸ“ˆ Performance Considerations

Bridge Overhead

  • Method delegation - Additional method calls through bridge
  • Object creation - Bridge object creation and management
  • Memory usage - Bridge object memory footprint
  • Interface calls - Virtual method call overhead

Optimization Techniques

  • Object pooling - Reuse bridge objects when possible
  • Caching - Cache expensive bridge operations
  • Lazy initialization - Defer bridge creation until needed
  • Connection pooling - Reuse expensive connections


πŸ“š Best Practices

1. Bridge Design

  • Clear separation - Maintain clear boundaries between abstraction and implementation
  • Stable interfaces - Design stable abstraction and implementation interfaces
  • Single responsibility - Each bridge component should have one clear purpose
  • Documentation - Document the relationship between abstractions and implementations

2. Implementation Guidelines

  • Interface design - Design clean, stable interfaces for both abstraction and implementation
  • Error handling - Proper error handling in both abstraction and implementation layers
  • Resource management - Properly manage resources in implementation layer
  • Testing strategies - Test abstractions and implementations separately

3. Performance Optimization

  • Minimize overhead - Keep bridge overhead minimal
  • Efficient delegation - Optimize method delegation
  • Object reuse - Reuse bridge objects when possible
  • Connection pooling - Pool expensive connections

🎯 Conclusion

The Bridge Pattern provides a powerful way to decouple abstraction from implementation, enabling flexible, extensible systems. By creating a bridge between abstraction and implementation, it enables:

  • Independent evolution of abstractions and implementations
  • Flexible combinations of different abstractions and implementations
  • Easy extension without modifying existing code
  • Better maintainability through clear separation of concerns

This pattern is essential for building flexible, maintainable systems that need to support multiple implementations or platforms. Whether you’re building cross-platform applications, integrating multiple services, or creating extensible frameworks, the Bridge Pattern provides the foundation for robust, flexible system design.

Next Steps:

  • Explore the Adapter Pattern for interface compatibility
  • Learn about the [Strategy Pattern] for runtime behavior switching
  • Discover the Factory Method Pattern for creating implementations

Ready to implement the Bridge Pattern in your projects? Download the complete code examples from our design_pattern repository and start building more flexible, extensible systems today!




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • How to Use Multiple GitHub Accounts on One Computer: Complete SSH Setup Guide
  • Excalidraw AI: Create Professional Diagrams with Text Commands - Complete Guide
  • Complete macOS Development Environment Setup Guide for 2024
  • Design Pattern 28: Interpreter Pattern - Complete Guide with Examples
  • Design Pattern 27: Visitor Pattern - Complete Guide with Real-World IoT Examples