
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Input Output Operations
- C++ Basic Input/Output
- C++ Cin
- C++ Cout
- C++ Manipulators
- Type System & Data Representation
- C++ Modifier Types
- C++ Storage Classes
- C++ Constexpr Specifier
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Scope Resolution Operator
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ Jump Statements
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Return Values
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Array Decay
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Destructors
- C++ Virtual Destructor
- C++ Inheritance
- C++ Inheritance
- C++ Multiple Inheritance
- C++ Multilevel Inheritance
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ Override Specifiers
- C++ Final Specifiers
- C++ Design Patterns
- C++ Creational Design Patterns
- C++ Singleton Design Pattern
- C++ Factory Method Design Pattern
- C++ Abstract Factory Pattern
- C++ Prototype Design Pattern
- C++ Structural Design Patterns
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ nullptr
- C++ unordered_multiset
- C++ Structural Design Patterns
- C++ Adapter Pattern
- C++ Bridge Pattern
- C++ Composite Pattern
- C++ Decorator Pattern
Bridge Design Pattern in C++
Bridge Design Pattern is a structural design pattern which helps to separate the following two aspects of a software system −
- Abstraction − Provides the interface for client code, hiding the implementation details.
- Implementation − Provides the concrete implementation of the abstraction.
By separating the above aspects, we can make both the abstraction and implementation independently expandable. This means that we can add new abstractions and implementations without affecting existing code.

Think of it like a Coffee shop. You love coffee but alone it would be plain. Sometimes you want Espresso, sometimes Latte, and sometimes you want to add Milk, Sugar, or Honey.
The coffee type (Espresso, Latte) is the abstraction, and the add-ons (Milk, Sugar, Honey) are the implementations. Instead of creating separate classes for every possible combination (like "EspressoWithMilk" or "LatteWithSugar"), the Bridge Pattern lets coffee delegate to add-ons through composition. This makes the system more flexible, that allows new coffee types or new add-ons to be added without changing existing code, and avoids the explosion of subclasses.
Abstraction
The Abtraction here is not same as in Abstract classes or Interfaces. It is a higher level of abstraction that separates the interface from the implementation.
We only see "what" we need to see, instead of "how" it is implemented. The Abstraction contains a reference to the Implementor.

Implementor
The Implementor defines the interface for implementation classes. This interface doesn't have to be exactly match to Abstraction's interface; in fact, the two interfaces can be different. Typically, the Implementor interface provides only primitive operations, and Abstraction defines higher-level operations based on those primitives.
We don't care about "what" it does, we care about "how" it is done. The Implementor doesn't contain any reference to the Abstraction.

Implementation of Bridge Design Pattern in C++
Let's implement the Bridge Design Pattern in C++ using the coffee shop example mentioned earlier. We'll create an abstraction for Coffee and an implementor for AddOns.
Steps to Implement Bridge Design Pattern
Following image shows the steps to implement Bridge Design Pattern.

C++ Code for Bridge Design Pattern
In this example, we have an abstract class AddOn
that defines the interface for add-ons like Milk, Sugar, and Honey. The Coffee
class is the abstraction that contains a reference to an AddOn
. The concrete classes Espresso
and Latte
are refined abstractions that implement the serve()
method.
#include <iostream> using namespace std; // Implementor: AddOn class AddOn { public: virtual void add() = 0; }; // Concrete AddOn: Milk class Milk : public AddOn { public: void add() override { cout << "with Milk"; } }; // Concrete AddOn: Sugar class Sugar : public AddOn { public: void add() override { cout << "with Sugar"; } }; // Concrete AddOn: Honey class Honey : public AddOn { public: void add() override { cout << "with Honey"; } }; // Abstraction: Coffee class Coffee { protected: // Bridge AddOn* addon; public: Coffee(AddOn* a) : addon(a) {} virtual void serve() = 0; }; // Refined Abstraction: Espresso class Espresso : public Coffee { public: Espresso(AddOn* a) : Coffee(a) {} void serve() override { cout << "Espresso "; addon->add(); cout << endl; } }; // Refined Abstraction: Latte class Latte : public Coffee { public: Latte(AddOn* a) : Coffee(a) {} void serve() override { cout << "Latte "; addon->add(); cout << endl; } }; // Client int main() { AddOn* milk = new Milk(); AddOn* sugar = new Sugar(); // Espresso with Milk Coffee* espressoMilk = new Espresso(milk); // Latte with Sugar Coffee* latteSugar = new Latte(sugar); espressoMilk->serve(); latteSugar->serve(); delete milk; delete sugar; delete espressoMilk; delete latteSugar; }
Following is the output of the above code −
Espresso with Milk Latte with Sugar
In this implementation, we can easily add new types of coffee or new add-ons without modifying existing code. For example, we can create a new class Mocha
that extends Coffee
or a new class Caramel
that extends AddOn
, and the existing classes will remain unaffected.
When to Use Bridge Design Pattern
- Change how things work without changing what they do − Use Bridge to swap or update implementations anytime.
- Grow both sides easily − Add new features or new ways of doing things without breaking old code.
- Keep code clean and easy to change − Bridge keeps things simple and ready for easy updates.
- Handle lots of choices and combinations − Manage many types and options without confusion.
- Avoid too many classes − Prevent a mess of classes for every mixâuse composition instead.
Real-world Software Use-cases of Bridge Design Pattern
Following is a diagram that shows some real-world software use-cases of Bridge Design Pattern.

Conclusion
In this chapter, we learned about the Bridge Design Pattern, which is a structural design pattern that separates an abstraction from its implementation. We discussed the components of the pattern, including Abstraction and Implementor, and saw how they work together and provide way to extend both independently and maintain flexibility(composition over inheritance). We also implemented the Bridge Design Pattern in C++ using a coffee shop example, demonstrating how to create abstractions for Coffee and implementors for AddOns. Finally, we explored when to use the Bridge Design Pattern and some real-world software use-cases.