java bridge pattern
java bridge pattern
Bridge Pattern in Java
The Bridge Pattern is a design pattern that separates an abstraction from its implementation so that the two can vary independently.
Let's consider a real-world scenario where we have a simple console game that displays different types of graphics. The game has different graphic modes like text, ASCII art, and high-quality graphics. Each mode has its own way of displaying the game's elements, but they all share the same core functionality.
Abstract Class: GraphicMode
We can start by defining an abstract class GraphicMode
that provides a basic interface for all types of graphic modes:
public abstract class GraphicMode {
public abstract void display();
}
Concrete Classes: TextGraphic
, ASCIIArtGraphic
, and HQGraphic
Now, let's create three concrete classes that implement the GraphicMode
interface. Each class represents a specific type of graphic mode:
TextGraphic
: Displays text-based graphics.
public class TextGraphic extends GraphicMode {
@Override
public void display() {
System.out.println("Displaying text graphics...");
}
}
ASCIIArtGraphic
: Displays ASCII art graphics.
public class ASCIIArtGraphic extends GraphicMode {
@Override
public void display() {
System.out.println("Displaying ASCII art graphics...");
}
}
HQGraphic
: Displays high-quality graphics.
public class HQGraphic extends GraphicMode {
@Override
public void display() {
System.out.println("Displaying high-quality graphics...");
}
}
Refined Abstraction: Game
We can then create a refined abstraction, Game
, that depends on the concrete classes (graphic modes). This allows us to vary the graphic mode without changing the Game
class.
public abstract class Game {
private GraphicMode graphicMode;
public Game(GraphicMode graphicMode) {
this.graphicMode = graphicMode;
}
public void play() {
graphicMode.display();
}
}
Concrete Game Classes:
Now, we can create concrete game classes that use the different graphic modes:
public class TextGame extends Game {
public TextGame() {
super(new TextGraphic());
}
}
public class ASCIIArtGame extends Game {
public ASCIIArtGame() {
super(new ASCIIArtGraphic());
}
}
public class HQGame extends Game {
public HQGame() {
super(new HQGraphic());
}
}
Benefits:
The Bridge Pattern provides several benefits:
Decoupling: TheGame
class is decoupled from the specific graphic modes, making it easier to add or change graphic modes without affecting the game. Polymorphism: The Game
class can work with different types of graphic modes, which allows for polymorphic behavior. Extension: New graphic modes can be added without modifying the Game
class.
In conclusion, the Bridge Pattern in Java provides a way to separate an abstraction from its implementation, allowing for more flexibility and extensibility. It's particularly useful when you need to vary an abstraction's implementation without affecting its interface or behavior.
Java adapter tutorial
Here is a comprehensive tutorial on Java adapter design pattern:
Introduction
The Adapter design pattern is a structural pattern that allows two incompatible objects to collaborate and work together seamlessly. It's used when you have an existing object that needs to be adapted to fit another system, framework, or technology. This pattern helps decouple the dependencies between classes, making your code more modular and easier to maintain.
Problem Statement
Suppose we have a SoundSystem
interface with two methods: playMusic()
and playMovie()
. We want to use this interface with an existing class called DVDPlayer
, but DVDPlayer
only knows how to play movies. The problem is that DVDPlayer
does not implement the SoundSystem
interface, so we can't directly use it with our system.
Solution
To solve this issue, we'll create a DVDAdapter
class that acts as an intermediary between DVDPlayer
and SoundSystem
. This adapter class will translate the playMovie()
method of DVDPlayer
into something that the SoundSystem
can understand.
Here's the code for the DVDAdapter
class:
public class DVDAdapter implements SoundSystem {
private DVDPlayer dvdPlayer;
public DVDAdapter(DVDPlayer dvdPlayer) {
this.dvdPlayer = dvdPlayer;
}
@Override
public void playMusic() {
// Translate playMusic() method to movie playing
dvdPlayer.playMovie();
}
}
How it Works
The DVDAdapter
class implements the SoundSystem
interface, which means it provides an implementation for all methods declared in that interface. In our case, we only need to implement the playMusic()
method.
When you create a DVDAdapter
instance and pass an existing DVDPlayer
object to its constructor, it will use the DVDPlayer
's playMovie()
method under the hood whenever someone calls playMusic()
on that adapter.
Benefits
Using the Adapter pattern in Java provides several benefits:
Decoupling: TheDVDAdapter
class acts as a bridge between DVDPlayer
and the rest of your system, allowing them to collaborate without having direct dependencies. Extensibility: By creating adapters for different classes, you can easily adapt new classes that come along in the future. Reusability: The adapter pattern makes it easy to reuse existing classes with other parts of your system.
Conclusion
In this tutorial, we learned how to use Java's Adapter design pattern to enable two incompatible objects to work together seamlessly. We created a DVDAdapter
class that acts as an intermediary between DVDPlayer
and the SoundSystem
interface, allowing us to play movies using the playMusic()
method. This pattern helps decouple dependencies between classes, making our code more modular and easier to maintain.