Bridge pattern
Image taken from ReplayBird
The objective of this post is to explain and show how to implement the Bridge pattern
Pre-requisites
Check all the description and information related to the Bridge Pattern and return here to see a practical example.
Description
Imagine that you are creating a new graphics engine and this engine needs to be able to run on the different operating systems Like Windows
, Linux
and OSX
.
As you delve deeper into the development process, you encounter a significant hurdle: the diverse Graphics APIs supported by each operating system.
Your initial approach involves creating separate classes to implement the functionality for each Graphics API, resulting in DirectxApi
, OpenGlApi
, and VulkanApi
.
However, as your codebase grows, maintaining these distinct classes becomes increasingly unwieldy.
With the Bridge Pattern, you're presented with an elegant solution to this conundrum. By adopting the Bridge Pattern, you can effectively separate the abstraction of the graphics functionality from the platform-specific implementations. Let's explore how the Bridge Pattern transforms your approach and mitigates the challenges of managing a growing codebase.
Before implementing this pattern
Start defining an abstraction layer that encapsulates the high-level graphics functionality your engine provides. This abstraction serves as a contract between the client code and the platform-specific implementations, allowing for seamless interaction without exposing the underlying complexities.
Next, you create platform-specific implementation classes, such as OpenGLRenderer
, Direct3DRenderer
, and VulkanRenderer
, each tailored to interact with the respective operating system's Graphics API.
These implementation classes adhere to the common interface defined by the abstraction layer, ensuring interchangeable compatibility.
Adapting to Growth
As your graphics engine evolves and grows in complexity, the Bridge Pattern offers unparalleled flexibility and scalability. Adding support for new operating systems or Graphics APIs becomes a streamlined process of creating additional implementation classes that adhere to the existing abstraction. This modular approach minimizes code duplication and promotes code reuse, simplifying maintenance and future expansion efforts.
Furthermore, the Bridge Pattern facilitates code maintainability by isolating changes to specific implementation details, preventing ripple effects throughout the codebase. Whether you're optimizing performance for a specific platform or integrating new features, the Bridge Pattern empowers you to make targeted modifications without disrupting the overall architecture.
Code Implementation
To implement the pattern we need to create an interface that has the common methods that our code needs to work, this interface helps us to create platform specific implementation
public interface IGraphicsRenderer
{
unsafe void OnLoad();
unsafe void OnRender(double obj);
void OnUpdate(double obj);
void OnFramebufferResize(Vector2D<int> newSize);
void OnClose();
void AddFigure(Figure figure);
}
with this implementation we can create our Direct3DRenderer
or OpenGLRenderer
Please visit the source code for the custom implementations
At this point we have the main functionality done, but we can create our Abstraction which defines the high-level interface for clients to interact with our engine GraphicsAbstraction
Diagram
Result
Running the application on Windows
will use Direct3D
by default
but what happens if we run this application on Linux
and force the system to use Direct3D
instead of OpenGL
?
In this scenario we are going to use Linux Fedora 40 workstation to run this code
As you can see it is not possible to run Direct3D on Linux
because it is designed to run on Windows
Microsoft DirectX is a collection of application programming interfaces for handling tasks related to multimedia, especially game programming and video, on Microsoft platforms. — Source: Wikipedia
This is where the Bridge pattern comes into play, you can have multiple implementations of the same interface but the result is the same, the expected result is to see the same figures that you see on Windows
but in this case using OpenGL
and running on Linux
.