Adapter design pattern Java example
Adapter design pattern Java example
Here's an example of the Adapter Design Pattern in Java:
Let's say we have a class Target
that expects to work with an object of type Adaptee
, but what if we want to use a different object, let's call it Adaptor
, that doesn't implement Adaptee
directly? We can create an adapter that implements the target interface and uses the adaptee inside. This is exactly what the Adapter pattern does.
Here's an example:
// Adaptee (old API)
interface Adaptee {
String make();
}
class OldPhone implements Adaptee {
public String make() {
return "Old Phone Make: RING";
}
}
// Target (new API)
interface Target {
String request();
}
// Adaptor
class PhoneAdaptor implements Target {
private Adaptee adaptee;
public PhoneAdaptor(Adaptee adaptee) {
this.adaptee = adaptee;
}
public String request() {
return "Phone Request: " + adaptee.make();
}
}
public class Main {
public static void main(String[] args) {
// Using the Adaptee directly
OldPhone oldPhone = new OldPhone();
System.out.println(oldPhone.make()); // Output: Old Phone Make: RING
// Creating an adapter for the OldPhone
OldPhone oldPhoneAdaptor = new OldPhone();
Target phoneAdaptor = new PhoneAdaptor(oldPhoneAdaptor);
// Using the target interface
System.out.println(phoneAdaptor.request()); // Output: Phone Request: RING
}
}
In this example, we have an OldPhone
class that implements the Adaptee
interface. We also have a Target
interface and a PhoneAdaptor
class that implements this target interface.
The PhoneAdaptor
class uses an instance of OldPhone
to fulfill its contract with the Target
interface. This way, we can seamlessly integrate an old API (represented by the Adaptee
) into our new system (represented by the Target
).
By using an adapter to translate between different APIs, we make it possible for these APIs to work together in a single system.
The Adapter pattern is commonly used when:
We have two incompatible interfaces that need to be integrated. There's no feasible way to change one interface to match the other. We can't modify the existing API but still want to use it with another part of our application.In summary, the Adapter Design Pattern helps us integrate different APIs or objects by converting them into a compatible form. It does this by using an adapter class that implements the target interface and uses the adaptee inside.
What is an example of an adapter in Java?
I'll respond in English this time.
In the context of object-oriented programming (OOP) and Java, specifically, an adapter is a design pattern that allows two incompatible objects to work together seamlessly. This compatibility issue often arises when you have different interfaces or classes with incompatible methods or behaviors.
The Adapter pattern helps bridge this gap by transforming one interface into another, making it possible for them to collaborate effectively. In essence, the adapter acts as a translator between these two interfaces, ensuring that they can communicate efficiently and without errors.
A classic example of an adapter in Java is a USB-to-Ethernet adapter. Imagine you have a USB-enabled device, such as a flash drive, and another device that only communicates through Ethernet (e.g., a computer or network printer). The two devices don't share the same communication protocol, but with an adapter, they can still interact.
To illustrate this concept using Java code, let's consider a simple scenario:
Suppose you have a USBFlashDrive
class that has methods like read()
and write()
, which are specific to USB operations. Meanwhile, you have another class called NetworkPrinter
with methods like print()
and scan()
, which operate within an Ethernet network.
public interface USBInterface {
void read();
void write();
}
public interface NetworkInterface {
void print();
void scan();
}
public class USBFlashDrive implements USBInterface {
@Override
public void read() {
System.out.println("Reading from USB flash drive...");
}
@Override
public void write() {
System.out.println("Writing to USB flash drive...");
}
}
public class NetworkPrinter implements NetworkInterface {
@Override
public void print() {
System.out.println("Printing on network printer...");
}
@Override
public void scan() {
System.out.println("Scanning with network printer...");
}
}
In this scenario, the USBFlashDrive
and NetworkPrinter
classes represent different interfaces (USB and Ethernet) that need to work together. To enable this collaboration, you can create an adapter class that implements both interfaces.
Here's an example of such an adapter:
public class USBToEthernetAdapter implements NetworkInterface {
private final USBInterface usbFlashDrive;
public USBToEthernetAdapter(USBInterface usbFlashDrive) {
this.usbFlashDrive = usbFlashDrive;
}
@Override
public void print() {
// Convert print operation to USB-specific equivalent
usbFlashDrive.write();
System.out.println("Printing equivalent executed...");
}
@Override
public void scan() {
// Convert scan operation to USB-specific equivalent
usbFlashDrive.read();
System.out.println("Scanning equivalent executed...");
}
}
In this adapter, you can see how the USBInterface
methods (read()
and write()
) are used to implement the corresponding NetworkInterface
methods (print()
and scan()
). This allows the USB-enabled flash drive and network printer to communicate effectively through the adapter.
When you create an instance of the USBToEthernetAdapter
class and pass the USBFlashDrive
object as a parameter, you can use the adapter to bridge the gap between the two interfaces:
public class Main {
public static void main(String[] args) {
USBInterface usbFlashDrive = new USBFlashDrive();
NetworkPrinter networkPrinter = new NetworkPrinter();
// Create an adapter instance with the flash drive as a parameter
NetworkInterface ethernetAdapter = new USBToEthernetAdapter(usbFlashDrive);
// Now you can use the adapter to interact with the network printer
ethernetAdapter.print(); // Equivalent of writing to the flash drive
ethernetAdapter.scan(); // Equivalent of reading from the flash drive
}
}
In this example, the USBToEthernetAdapter
class serves as a bridge between the USBFlashDrive
and NetworkPrinter
objects. By implementing both interfaces and converting operations between them, the adapter enables seamless collaboration between these two incompatible objects.
In summary, an adapter in Java is a design pattern that allows two disparate objects or classes to work together efficiently by transforming one interface into another. This pattern helps bridge the gap between different interfaces, enabling effective communication and collaboration between objects with incompatible methods or behaviors.