mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-08-16 00:24:06 +00:00
docs: collecting parameter docs + formatting
This commit is contained in:
+55
-27
@@ -20,15 +20,20 @@ Decouple an abstraction from its implementation so that the two can vary indepen
|
||||
|
||||
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.
|
||||
> 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 to inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
|
||||
> Bridge pattern is about preferring composition to 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"
|
||||
> 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**
|
||||
|
||||
@@ -37,8 +42,11 @@ Translating our weapon example from above. Here we have the `Weapon` hierarchy:
|
||||
```java
|
||||
public interface Weapon {
|
||||
void wield();
|
||||
|
||||
void swing();
|
||||
|
||||
void unwield();
|
||||
|
||||
Enchantment getEnchantment();
|
||||
}
|
||||
|
||||
@@ -112,7 +120,9 @@ Here's the separate enchantment hierarchy:
|
||||
```java
|
||||
public interface Enchantment {
|
||||
void onActivate();
|
||||
|
||||
void apply();
|
||||
|
||||
void onDeactivate();
|
||||
}
|
||||
|
||||
@@ -157,16 +167,16 @@ Here are both hierarchies in action:
|
||||
|
||||
```java
|
||||
LOGGER.info("The knight receives an enchanted sword.");
|
||||
var enchantedSword = new Sword(new SoulEatingEnchantment());
|
||||
enchantedSword.wield();
|
||||
enchantedSword.swing();
|
||||
enchantedSword.unwield();
|
||||
var enchantedSword=new Sword(new SoulEatingEnchantment());
|
||||
enchantedSword.wield();
|
||||
enchantedSword.swing();
|
||||
enchantedSword.unwield();
|
||||
|
||||
LOGGER.info("The valkyrie receives an enchanted hammer.");
|
||||
var hammer = new Hammer(new FlyingEnchantment());
|
||||
hammer.wield();
|
||||
hammer.swing();
|
||||
hammer.unwield();
|
||||
LOGGER.info("The valkyrie receives an enchanted hammer.");
|
||||
var hammer=new Hammer(new FlyingEnchantment());
|
||||
hammer.wield();
|
||||
hammer.swing();
|
||||
hammer.unwield();
|
||||
```
|
||||
|
||||
Here's the console output.
|
||||
@@ -196,37 +206,55 @@ The item's glow fades.
|
||||
|
||||
Use the Bridge pattern when
|
||||
|
||||
* You want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.
|
||||
* Both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
|
||||
* Changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
|
||||
* You have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies.
|
||||
* You want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation.
|
||||
* You want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for
|
||||
example, when the implementation must be selected or switched at run-time.
|
||||
* Both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern
|
||||
lets you combine the different abstractions and implementations and extend them independently.
|
||||
* Changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have
|
||||
to be recompiled.
|
||||
* You have a proliferation of classes. Such a class hierarchy indicates the need for splitting an object into two parts.
|
||||
Rumbaugh uses the term "nested generalizations" to refer to such class hierarchies.
|
||||
* You want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be
|
||||
hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same
|
||||
string representation.
|
||||
|
||||
## Known uses
|
||||
|
||||
* GUI Frameworks where the abstraction is the window, and the implementation could be the underlying OS windowing system.
|
||||
* Database Drivers where the abstraction is a generic database interface, and the implementations are database-specific drivers.
|
||||
* Device Drivers where the abstraction is the device-independent code, and the implementation is the device-dependent code.
|
||||
* GUI Frameworks where the abstraction is the window, and the implementation could be the underlying OS windowing
|
||||
system.
|
||||
* Database Drivers where the abstraction is a generic database interface, and the implementations are database-specific
|
||||
drivers.
|
||||
* Device Drivers where the abstraction is the device-independent code, and the implementation is the device-dependent
|
||||
code.
|
||||
|
||||
## Consequences
|
||||
|
||||
Benefits:
|
||||
|
||||
* Decoupling Interface and Implementation: The Bridge pattern enhances modularity by separating the interface (the high-level operations) from the implementation (the low-level operations).
|
||||
* Decoupling Interface and Implementation: The Bridge pattern enhances modularity by separating the interface (the
|
||||
high-level operations) from the implementation (the low-level operations).
|
||||
* Improved Extensibility: You can extend the abstraction and implementation hierarchies independently.
|
||||
* Hiding Implementation Details: Clients only see the abstraction's interface, not its implementation.
|
||||
|
||||
Trade-offs:
|
||||
|
||||
* Increased Complexity: The pattern can complicate the system architecture and code, especially for clients unfamiliar with the pattern.
|
||||
* Runtime Overhead: The extra layer of abstraction can introduce a performance penalty, although it is often negligible in practice.
|
||||
* Increased Complexity: The pattern can complicate the system architecture and code, especially for clients unfamiliar
|
||||
with the pattern.
|
||||
* Runtime Overhead: The extra layer of abstraction can introduce a performance penalty, although it is often negligible
|
||||
in practice.
|
||||
|
||||
## Related Patterns
|
||||
|
||||
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern is used to provide a different interface to an object, while the Bridge pattern is used to separate an object's interface from its implementation.
|
||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern is like the Bridge pattern, but with a different intent. Both patterns are based on composition: Strategy uses composition to change the behavior of a class, while Bridge uses composition to separate an abstraction from its implementation.
|
||||
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): The Abstract Factory pattern can be used along with the Bridge pattern to create platforms that are independent of the concrete classes used to create their objects.
|
||||
* [Composite](https://java-design-patterns.com/patterns/composite/): The Bridge pattern is often used with the Composite pattern to model the implementation details of a component.
|
||||
* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern is used to provide a different
|
||||
interface to an object, while the Bridge pattern is used to separate an object's interface from its implementation.
|
||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern is like the Bridge pattern, but
|
||||
with a different intent. Both patterns are based on composition: Strategy uses composition to change the behavior of a
|
||||
class, while Bridge uses composition to separate an abstraction from its implementation.
|
||||
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): The Abstract Factory pattern can be
|
||||
used along with the Bridge pattern to create platforms that are independent of the concrete classes used to create
|
||||
their objects.
|
||||
* [Composite](https://java-design-patterns.com/patterns/composite/): The Bridge pattern is often used with the Composite
|
||||
pattern to model the implementation details of a component.
|
||||
|
||||
## Tutorials
|
||||
|
||||
|
||||
Reference in New Issue
Block a user