The Bridge Pattern
This post is a cross-post from www.ModernesCpp.com.
The Bridge Pattern is a structural pattern. It decouples the interface from the implementation. In C++, a simplified version is often used: the Pimpl Idiom.
Before I write about the Pimpl Idiom, here are the fact about the Bridge Pattern
The Bridge Pattern
Purpose
Also known as
Applicability
Structure
Abstraction
RedefinedAbstraction
Implementor
ConcreteImplementor
The Bridge Pattern has two hierarchies. One hierarchy for the abstraction (interface), and one for the implementation. The client programs against the abstraction, and the abstraction uses the implementation. Consequentially, different implementations of the abstraction interface and different implementations of the implementation interface can be used transparently. The Bridge Pattern provides big flexibility because the abstraction and the implementation can be varied and can be exchanged during the run time of the program.
The Bridge Pattern is a powerful example exemplifying the combination of inheritance and composition. On one hand, it has two type hierarchies (inheritance), and on the other hand, the abstraction has an implementation (composition).
Example
The example shows a straightforward implementation of the Bridget Pattern.
// bridge.cpp
#include <iostream>
class Implementor { // (1)
public:
virtual void implementation() const = 0;
virtual ~Implementor() = default;
};
class ImplementorA: public Implementor {
public:
ImplementorA() = default;
void implementation() const {
std::cout << "ImplementatorA::implementation" << '\n';
}
};
class ImplementorB: public Implementor {
public:
ImplementorB() = default;
void implementation() const {
std::cout << "ImplementatorB::implementation" << '\n';
}
};
class Abstraction { // (2)
public:
virtual void function() const = 0;
virtual ~Abstraction() = default;
};
class RefinedAbstraction: public Abstraction {
public:
RefinedAbstraction(Implementor& impl) :
implementor(impl) {
}
void function() const {
std::cout << "RefinedAbstraction::function\n";
implementor.implementation();
}
private:
Implementor& implementor;
};
int main() {
std::cout << '\n';
ImplementorA implementorA;
ImplementorB implementorB;
RefinedAbstraction refinedAbstraction1(implementorA); // (3)
RefinedAbstraction refinedAbstraction2(implementorB); // (4)
Abstraction *abstraction1 = &refinedAbstraction1;
Abstraction *abstraction2 = &refinedAbstraction2;
abstraction1->function();
std::cout << '\n';
abstraction2->function();
std::cout << '\n';
}
The class Implementor (line 1) is the interface for the implementation hierarchy, and the class Abstraction (line 2) is the interface of the abstraction. The instances redefinedAbstraction1 and redefinedAbstraction2 get their implementation in its constructor (lines 3 and 4).
The following screenshot shows the output of the program.
Related Patterns
In C++, a simplified version of the Bridge Pattern is often used.
Modernes C++ Mentoring
Get the invitation to the one-hour presentation of my mentoring program "Fundamentals for C++ Professionals" including Q&A
Do you want the invitation to the Zoom meeting?
???Write an e-mail with the subject 2022-10-24 to [email protected].
领英推荐
The Pimpl Idiom
The key idea of the Pimpl Idiom is that the implementation of the class is hidden behind a pointer.
Here is a recipe for implementing the Pimpl Idiom:
Bartlomiej Filipek provides in his blog post "The Pimpl Pattern - what you should know" a nice example of the Pimpl Idiom:
// class.h
class MyClassImpl;
class MyClass
{
public:
explicit MyClass();
~MyClass();
// movable:
MyClass(MyClass && rhs) noexcept; // (2)
MyClass& operator=(MyClass && rhs) noexcept; // (3)
// and copyable
MyClass(const MyClass& rhs); // (4)
MyClass& operator=(const MyClass& rhs); // (5)
void DoSth();
void DoConst() const;
private:
const MyClassImpl* Pimpl() const { return m_pImpl.get(); } // (6)
MyClassImpl* Pimpl() { return m_pImpl.get(); } // (7)
std::unique_ptr<MyClassImpl> m_pImpl; // (1)
};
// class.cpp
class MyClassImpl
{
public:
~MyClassImpl() = default;
void DoSth() { }
void DoConst() const { }
};
MyClass::MyClass() : m_pImpl(new MyClassImpl())
{
}
MyClass::~MyClass() = default;
MyClass::MyClass(MyClass &&) noexcept = default;
MyClass& MyClass::operator=(MyClass &&) noexcept = default;
MyClass::MyClass(const MyClass& rhs)
: m_pImpl(new MyClassImpl(*rhs.m_pImpl))
{}
MyClass& MyClass::operator=(const MyClass& rhs) {
if (this != &rhs)
m_pImpl.reset(new MyClassImpl(*rhs.m_pImpl));
return *this;
}
void MyClass::DoSth()
{
Pimpl()->DoSth();
}
void MyClass::DoConst() const
{
Pimpl()->DoConst();
}
Here are the key ideas of his implementation. I added a few line markers:
You may ask yourself. What are the benefits of the Pimpl Idiom? It would be easier to merge the implementation MyClassImpl into the abstraction MyClass.
Pros and Cons
Let me start with the pros
Pros
Cons
What's Next?
Additionally, the Decorator Pattern is an often-used structural pattern from the book "Design Patterns: Elements of Reusable Object-Oriented Software". Its job is to extend an object with responsibilities dynamically. Let me present the Decorator in my next post.
?
?
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dr?ge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschl?ger, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, and Wolfgang Fütterer.
Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, Ralf Abramowitsch, John Nebel, Mipko, and Alicja Kaminska.
My special thanks to Embarcadero
My special thanks to PVS-Studio
?
Seminars
I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
Bookable (Online)
German
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
New
Contact Me