Also when:
A
/ \
Aa Ab
/ \ / \
Aa1 Aa2 Ab1 Ab2
Then the Bridge pattern allows you to change to:
A N
/ \ / \
Aa(N) Ab(N) 1 2
As the saying goes “Composition over inheritance“. Is it true? In some cases, yes, if it is as in the example above, we have a lot of derived classes in this example:
It’s better to create something based on this using the Bridge pattern:
Below is the UML diagram of the Bridge, which clearly shows that the client does not want to know the details of the implementation, and that the object’s abstraction is separated from the implementation.
And now an example in the form of a code:
class Program
{
static void Main(string[] args)
{
var classimplementationfirst = new BridgeImplementation(new ClassImplementationFirst());
classimplementationfirst.GetMethod();
Console.ReadKey();
}
}
abstract class Bridge
{
private IIntefaceEncapsulation interfaceencapsulation;
public Bridge(IIntefaceEncapsulation interfaceencapsulation)
{
this.interfaceencapsulation = interfaceencapsulation;
}
public void DoMethodOne()
{
interfaceencapsulation.DoMethodOne();
}
public void DoMethodTwo()
{
interfaceencapsulation.DoMethodTwo();
}
}
class BridgeImplementation : Bridge
{
public BridgeImplementation(IIntefaceEncapsulation interfaceencapsulation):base(interfaceencapsulation){}
public void GetMethod()
{
DoMethodOne();
DoMethodTwo();
}
}
interface IIntefaceEncapsulation
{
void DoMethodOne();
void DoMethodTwo();
}
class ClassImplementationFirst : IIntefaceEncapsulation
{
public void DoMethodOne()
{
throw new NotImplementedException();
}
public void DoMethodTwo()
{
throw new NotImplementedException();
}
}
class ClassImplementationSecond : IIntefaceEncapsulation
{
public void DoMethodOne()
{
throw new NotImplementedException();
}
public void DoMethodTwo()
{
throw new NotImplementedException();
}
}
Of course, the abstraction is the Bridge class, using dependency injection we inject into the constructor of the BridgeImplementation class, which inherits from the Bridge class the object of the class we want to operate on and we call its methods in the client.
In order to better understand the separation of the implementation from the object’s abstraction, I will use a picture that I found somewhere in the network that illustrates well the operation of the bridge, that is separating the implementation from the interface.
The abstraction is the Class of the Bridge, which illustrates what the button is supposed to do eg on the TV, the TV, radio or lamp object is already an implementation.
I will give an example from the picture, only we will move it to the code.
class Program
{
static void Main(string[] args)
{
Switch tvButton = new ClickSwitch(new TV());
tvButton.On();
tvButton.Off();
Switch radioButton = new ClickSwitch(new Radio());
radioButton.On();
radioButton.Off();
Switch lampButton = new ClickSwitch(new Lamp());
lampButton.On();
lampButton.Off();
Console.ReadKey();
}
}
abstract class Switch
{
protected IDevice device;
public Switch(IDevice device)
{
this.device = device;
}
public abstract void On();
public abstract void Off();
}
class ClickSwitch : Switch
{
public ClickSwitch(IDevice device):base(device)
{ }
public override void On()
{
device.On();
}
public override void Off()
{
device.Off();
}
}
interface IDevice
{
void On();
void Off();
}
class TV : IDevice
{
public void Off()
{
Console.WriteLine("the TV was turned off");
}
public void On()
{
Console.WriteLine("the TV was turned on");
}
}
class Radio : IDevice
{
public void Off()
{
Console.WriteLine("the radio was turned off");
}
public void On()
{
Console.WriteLine("the radio was turned on");
}
}
class Lamp : IDevice
{
public void Off()
{
Console.WriteLine("the lamp was turned off");
}
public void On()
{
Console.WriteLine("the lamp was turned on");
}
}
The bridge is here the abstract class Switch, implementation is the TV, Radio, Lamp classes.
The case looks similar to the previous example, to the class ClickSwitch, which inherits from the Switch class, we pass the class object to the constructor using dependency injection and call the On and Off methods.
Result
The Bridge pattern is quite similar to a facade or adapter. However, the facade differs mainly in that it simply has to provide a simple interface to the client, and the adapter has to combine non-matching interfaces, with smaller projects the implementation of these patterns does not differ much, however, in larger projects there are big differences.
That’s all about Bridge 🙂.
Link to github with the whole code from this article: https://github.com/Slaw145/BridgeTutorial
This content also you can find on my blog http://devman.pl/programtech/design-patterns-bridge/
If you recognise it as useful, share it with others so that others can also use it.
Leave upvote and follow and wait for next articles :) .
In the next article, we will talk about the Proxy pattern.
And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂
– site on fb: Devman.pl-Sławomir Kowalski
– group on fb: DevmanCommunity
Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.
Take care 🙂