YouTip LogoYouTip

Python Bridge

Bridge Pattern is a structural design pattern that separates the abstraction from its implementation, allowing them to vary independently. Simply put, it **splits multiple dimensions of change in a system, allowing each dimension to expand independently**.\n\n### Real-life Analogy of Bridge Pattern\n\nImagine the relationship between a remote control and a TV:\n\n* **Remote Control** (Abstraction): Provides control interfaces (power, volume, channel)\n* **TV** (Implementation): Executes specific operations (Sony TV, Samsung TV, Xiaomi TV)\n\nThe remote control doesn't need to know what type of TV it is, and the TV doesn't need to know what type of remote control it is. They are connected through a "bridge," allowing each to be upgraded independently.\n\n* * *\n\n## Why Do We Need Bridge Pattern?\n\n### Limitations of Traditional Approach\n\nSuppose we want to design a graphics drawing system that supports different shapes and colors:\n\n## Example\n\n# Traditional implementation - Class explosion problem\n\nclass RedCircle:\n\ndef draw(self):\n\nprint("Draw red circle")\n\nclass BlueCircle:\n\ndef draw(self):\n\nprint("DrawBlue Circle")\n\nclass RedRectangle:\n\ndef draw(self):\n\nprint("DrawRed Rectangle")\n\nclass BlueRectangle:\n\ndef draw(self):\n\nprint("DrawBlue Rectangle")\n\n# Every new color or shape requires creating a new class\n\n# 3 colors Γ— 3 shapes = 9 classes!\n\n### Advantages of Bridge Pattern\n\n## Example\n\n# Bridge pattern implementation\n\nclass Color:\n\n"""Color interface - Implementation part"""\n\ndef apply_color(self):\n\npass\n\nclass Shape:\n\n"""Shape abstraction - Abstraction part"""\n\ndef __init__ (self, color):\n\nself.color= color # The key to bridging!\n\ndef draw(self):\n\npass\n\n# Only need: 3 colors + 3 shapes = 6 classes\n\n# Instead of: 3 Γ— 3 = 9 classes\n\n* * *\n\n## Core Structure of Bridge Pattern\n\nLet's understand the components of bridge pattern through a complete example:\n\n!(#)\n\n### Four Key Roles\n\n1. **Abstraction**: Defines the abstract interface and maintains a reference to the implementation\n2. **RefinedAbstraction**: Extends the abstract interface\n3. **Implementor**: Defines the implementation interface\n4. **ConcreteImplementor**: Implements the interface concretely\n\n* * *\n\n## Complete Code Example: Graphics Drawing System\n\n### Step 1: Define Implementation Interface (Color)\n\n## Example\n\nfrom abc import ABC, abstractmethod\n\nclass Color(ABC):\n\n"""Color interface - Implementation part"""\n\n@abstractmethod\n\ndef apply_color(self):\n\npass\n\nclass Red(Color):\n\n"""Concrete implementation - Red"""\n\ndef apply_color(self):\n\nreturn"Red"\n\nclass Blue(Color):\n\n"""Concrete implementation - Blue"""\n\ndef apply_color(self):\n\nreturn"Blue"\n\nclass Green(Color):\n\n"""Concrete implementation - Green"""\n\ndef apply_color(self):\n\nreturn"Green"\n\n### Step 2: Define Abstraction Part (Shape)\n\n## Example\n\nclass Shape(ABC):\n\n"""Shape abstraction - Abstraction part"""\n\ndef __init__ (self, color: Color):\n\nself.color= color # Key to bridging: holds reference to implementation\n\n@abstractmethod\n\ndef draw(self):\n\npass\n\nclass Circle(Shape):\n\n"""Refined abstraction - Circle"""\n\ndef draw(self):\n\n color_name =self.color.apply_color()\n\nprint(f"Draw{color_name}circle")\n\nclass Rectangle(Shape):\n\n"""Refined abstraction - Rectangle"""\n\ndef draw(self):\n\n color_name =self.color.apply_color()\n\nprint(f"Draw{color_name}rectangle")\n\nclass Triangle(Shape):\n\n"""Refined abstraction - Triangle"""\n\ndef draw(self):\n\n color_name =self.color.apply_color()\n\nprint(f"Draw{color_name}triangle")\n\n### Step 3: Use Bridge Pattern\n\n## Example\n\n# Client code\n\ndef main():\n\n# Create color implementations\n\n red = Red()\n\n blue = Blue()\n\n green = Green()\n\n# Create shape abstractions and bridge color implementations\n\n red_circle = Circle(red)\n\n blue_rectangle = Rectangle(blue)\n\n green_triangle = Triangle(green)\n\n# Draw shapes\n\nprint("=== Shape Draw Result ===")\n\n red_circle.draw()# Output: DrawRed Circle\n\n blue_rectangle.draw()# Output: DrawBlue Rectangle\n\n green_triangle.draw()# Output: DrawGreen Triangle\n\n# Flexible combination: red rectangle\n\n red_rectangle = Rectangle(red)\n\n red_rectangle.draw()# Output: DrawRed Rectangle\n\nif __name__ =="__main__":\n\n main()\n\n* * *\n\n## Practical Application Scenarios\n\n### Scenario 1: Message Sending System\n\n## Example\n\nfrom abc import ABC, abstractmethod\n\n# Implementation part: Message sending methods\n\nclass MessageSender(ABC):\n\n@abstractmethod\n\ndef send(self, message):\n\npass\n\nclass EmailSender(MessageSender):\n\ndef send(self, message):\n\nreturn f"Sent via email:{message}"\n\nclass SMSSender(MessageSender):\n\ndef send(self, message):\n\nreturn f"Sent via SMS:{message}"\n\nclass WeChatSender(MessageSender):\n\ndef send(self, message):\n\nreturn f"Sent via WeChat:{message}"\n\n# Abstraction part: Message types\n\nclass Message(ABC):\n\ndef __init__ (self, sender: MessageSender):\n\nself.sender= sender\n\n@abstractmethod\n\ndef send(self):\n\npass\n\nclass UrgentMessage(Message):\n\ndef send(self):\n\n message =" " + self.get_content()\n\nreturn self.sender.send(message)\n\ndef get_content(self):\n\nreturn"System exception occurred, please handle immediately!"\n\nclass NormalMessage(Message):\n\ndef __init__ (self, sender: MessageSender, content):\n\nsuper(). __init__ (sender)\n\nself.content= content\n\ndef send(self):\n\nreturn self.sender.send(self.content)\n\n# Usage example\n\ndef message_example():\n\n email_sender = EmailSender()\n\n sms_sender = SMSSender()\n\n# Urgent message sent via SMS\n\n urgent_sms = UrgentMessage(sms_sender)\n\nprint(urgent_sms.send())# Sent via SMS: System exception occurred, please handle immediately!\n\n# Normal message sent via email\n\n normal_email = NormalMessage(email_sender,"Monthly report generated")\n\nprint(normal_email.send())# Sent via email: Monthly report generated\n\nmessage_example()\n\n### Scenario 2: Device Remote Control System\n\n## Example\n\n# Implementation part: Devices\n\nclass Device(ABC):\n\n@abstractmethod\n\ndef turn_on(self):\n\npass\n\n@abstractmethod\n\ndef turn_off(self):\n\npass\n\n@abstractmethod\n\ndef set_volume(self, volume):\n\npass\n\nclass TV(Device):\n\ndef turn_on(self):\n\nreturn"TV is on"\n\ndef turn_off(self):\n\nreturn"TV is off"\n\ndef set_volume(self, volume):\n\nreturn f"TV volume set to:{volume}"\n\nclass Radio(Device):\n\ndef turn_on(self):\n\nreturn"Radio is on"\n\ndef turn_off(self):\n\nreturn"Radio is off"\n\ndef set_volume(self, volume):\n\nreturn f"Radio volume set to:{volume}"\n\n# Abstraction part: Remote controls\n\nclass RemoteControl:\n\ndef __init__ (self, device: Device):\n\nself.device= device\n\ndef toggle_power(self):\n\nreturn"Toggle power state"\n\ndef volume_up(self):\n\nreturn"Volume increased"\n\ndef volume_down(self):\n\nreturn"Volume decreased"\n\nclass AdvancedRemoteControl(RemoteControl):\n\ndef mute(self):\n\nreturn"Mute mode"\n\ndef set_channel(self, channel):\n\nreturn f"Switch to channel:{channel}"\n\n# Usage example\n\ndef remote_example():\n\n tv = TV()\n\n radio = Radio()\n\nbasic_remote = RemoteControl(tv)\n\n advanced_remote = AdvancedRemoteControl(radio)\n\nprint(basic_remote.toggle_power())# Toggle power state\n\nprint(advanced_remote.mute())# Mute mode\n\nremote_example()\n\n* * *\n\n## Bridge Pattern Advantages Comparison\n\n| Feature | Traditional Approach | Bridge Pattern |\n| --- | --- | --- |\n| **Extensibility** | Poor, requires modifying existing code | Good, can be extended independently |\n| **Class Count** | Many, prone to class explosion | Few, linear growth |\n| **Maintainability** | Difficult, one change affects many | Easy, separated responsibilities |\n| **Flexibility** | Fixed combinations | Dynamic runtime combinations |\n\n* * *\n\n## Best Practices and Considerations\n\n### When to Use\n\nβœ… **Suitable for bridge pattern:**\n\n* When you need to extend in multiple dimensions independently\n* When you need to switch implementations at runtime\n* When you want to avoid permanent binding between abstraction and implementation\n* When inheritance would lead to overly complex class hierarchies\n\n❌ **Not suitable:**\n\n* When there are few dimensions of change, complex design isn't needed\n* When there's tight coupling between abstraction and implementation\n\n### Common Mistakes and How to Avoid\n\n## Example\n\n# Wrong example: Not truly decoupled\n\nclass BadShape:\n\ndef __init__ (self, color_type):\n\nif color_type =="red":\n\nself.color= Red()\n\nelif color_type =="blue":\n\nself.color= Blue()\n\n# Still need to modify this class to add new colors\n\n# Correct approach: Dependency injection\n\nclass GoodShape:\n\ndef __init__ (self, color: Color): # Depend on interface, not concrete implementation\n\nself.color= color\n\n* * *\n\n## Practice Tasks\n\n### Exercise 1: Extend Graphics System\n\nPlease add the following features to the graphics system:\n\n1. Add a new color (Yellow)\n2. Add a new shape (Ellipse)\n3. Create and draw a yellow ellipse\n\n### Exercise 2: Design Payment System\n\nDesign a payment system with requirements:\n\n* Payment methods: Alipay, WeChat Pay, Bank Card\n* Payment types: Normal payment, Installment payment, Combined payment\n* Use bridge pattern to ensure payment methods and types can be extended independently\n\n* * *\n\n## Summary\n\nBridge pattern provides great flexibility by **separating abstraction from implementation**. Its core ideas are:\n\n1. **Identify dimensions of change**: Find multiple dimensions in the system that may vary independently\n2. **Build the bridge**: Connect different dimensions through composition\n3. **Extend independently**: Each dimension can develop and change independently
← Python FlyweightPython Proxy β†’