Handle/Body
Decouple an abstraction from its implementation so that the two can vary independently.
Real-world example
Consider you have a weapon with different enchantments, and you are supposed to allow mixing different weapons with different enchantments. What would you do? Create multiple copies of each of the weapons for each of the enchantments or would you just create separate enchantment and set it for the weapon as needed? Bridge pattern allows you to do the second.
In Plain Words
Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
Wikipedia says
The bridge pattern is a design pattern used in software engineering that is meant to “decouple an abstraction from its implementation so that the two can vary independently”
Programmatic Example
Translating our weapon example from above. Here we have the Weapon
hierarchy:
1public interface Weapon {
2 void wield();
3 void swing();
4 void unwield();
5 Enchantment getEnchantment();
6}
7
8public class Sword implements Weapon {
9
10 private final Enchantment enchantment;
11
12 public Sword(Enchantment enchantment) {
13 this.enchantment = enchantment;
14 }
15
16 @Override
17 public void wield() {
18 LOGGER.info("The sword is wielded.");
19 enchantment.onActivate();
20 }
21
22 @Override
23 public void swing() {
24 LOGGER.info("The sword is swinged.");
25 enchantment.apply();
26 }
27
28 @Override
29 public void unwield() {
30 LOGGER.info("The sword is unwielded.");
31 enchantment.onDeactivate();
32 }
33
34 @Override
35 public Enchantment getEnchantment() {
36 return enchantment;
37 }
38}
39
40public class Hammer implements Weapon {
41
42 private final Enchantment enchantment;
43
44 public Hammer(Enchantment enchantment) {
45 this.enchantment = enchantment;
46 }
47
48 @Override
49 public void wield() {
50 LOGGER.info("The hammer is wielded.");
51 enchantment.onActivate();
52 }
53
54 @Override
55 public void swing() {
56 LOGGER.info("The hammer is swinged.");
57 enchantment.apply();
58 }
59
60 @Override
61 public void unwield() {
62 LOGGER.info("The hammer is unwielded.");
63 enchantment.onDeactivate();
64 }
65
66 @Override
67 public Enchantment getEnchantment() {
68 return enchantment;
69 }
70}
Here’s the separate enchantment hierarchy:
1public interface Enchantment {
2 void onActivate();
3 void apply();
4 void onDeactivate();
5}
6
7public class FlyingEnchantment implements Enchantment {
8
9 @Override
10 public void onActivate() {
11 LOGGER.info("The item begins to glow faintly.");
12 }
13
14 @Override
15 public void apply() {
16 LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
17 }
18
19 @Override
20 public void onDeactivate() {
21 LOGGER.info("The item's glow fades.");
22 }
23}
24
25public class SoulEatingEnchantment implements Enchantment {
26
27 @Override
28 public void onActivate() {
29 LOGGER.info("The item spreads bloodlust.");
30 }
31
32 @Override
33 public void apply() {
34 LOGGER.info("The item eats the soul of enemies.");
35 }
36
37 @Override
38 public void onDeactivate() {
39 LOGGER.info("Bloodlust slowly disappears.");
40 }
41}
Here are both hierarchies in action:
1LOGGER.info("The knight receives an enchanted sword.");
2var enchantedSword = new Sword(new SoulEatingEnchantment());
3enchantedSword.wield();
4enchantedSword.swing();
5enchantedSword.unwield();
6
7LOGGER.info("The valkyrie receives an enchanted hammer.");
8var hammer = new Hammer(new FlyingEnchantment());
9hammer.wield();
10hammer.swing();
11hammer.unwield();
Here’s the console output.
The knight receives an enchanted sword.
The sword is wielded.
The item spreads bloodlust.
The sword is swung.
The item eats the soul of enemies.
The sword is unwielded.
Bloodlust slowly disappears.
The valkyrie receives an enchanted hammer.
The hammer is wielded.
The item begins to glow faintly.
The hammer is swung.
The item flies and strikes the enemies finally returning to owner's hand.
The hammer is unwielded.
The item's glow fades.
Use the Bridge pattern when