From the Language of Code to Fairy Tales: Uniting Different Worlds with the Adapter Pattern
2023-06-15
Once upon a time, there were two friends from two different worlds: the Electric Vacuum Cleaner and the Electric Outlet. The Electric Vacuum Cleaner needed energy and wanted to get this energy from the Electric Outlet. However, there was a problem. The plug of the Electric Vacuum Cleaner did not fit the Electric Outlet. They were both produced in different standards and could not communicate directly with each other.
In this case, a hero emerged: the Adapter. The Adapter created a bridge between the plug of the Electric Vacuum Cleaner and the Electric Outlet. The plug of the Electric Vacuum Cleaner was plugged into one side of the Adapter and the other side of the Adapter was plugged into the Electric Outlet. Thus, the Electric Vacuum Cleaner got the energy and was able to perform its function.
This fairy tale explains the basic logic of the Adapter Pattern. The Adapter Pattern creates a bridge between two classes or interfaces that cannot communicate directly with each other. In this way, it transforms the interface of a class into the interface shape that another class expects.
As you can see in the diagram, the Target class is used by the Adapter class. The Adapter class transforms the specificRequest method of the Adaptee class into a request method that the Target class can understand.
Below you can find examples of the Adapter Pattern in C#, Java, Go, and Rust languages.
C#
// Target
public interface ITarget
{
string Request();
}
// Adaptee
public class Adaptee
{
public string SpecificRequest()
{
return "Specific Request";
}
}
// Adapter
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public string Request()
{
return _adaptee.SpecificRequest();
}
}
Java
// Target
public interface Target {
String request();
}
// Adaptee
public class Adaptee {
public String specificRequest() {
return "Specific Request";
}
}
// Adapter
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public String request() {
return adaptee.specificRequest();
}
}
Go
// Target
type Target interface {
Request() string
}
// Adaptee
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() string {
return "Specific Request"
}
// Adapter
type Adapter struct {
Adaptee *Adaptee
}
func (a *Adapter) Request() string {
return a.Adaptee.SpecificRequest()
}
Rust
// Target
pub trait Target {
fn request(&self) -> &'static str;
}
// Adaptee
pub struct Adaptee;
impl Adaptee {
pub fn specific_request(&self) -> &'static str {
"Specific Request"
}
}
// Adapter
pub struct Adapter {
adaptee: Adaptee,
}
impl Target for Adapter {
fn request(&self) -> &'static str {
self.adaptee.specific_request()
}
}
In these examples, the Adapter class or struct transforms the specificRequest method of the Adaptee class or struct into the request method of the Target interface or trait. In this way, the codes using
When we examine the examples of the Adapter Pattern in these four languages, we can see that each language exhibits a different approach according to its own characteristics. However, the basic principle is the same: a class or structure (Adaptee) is made usable by another class or structure (Target).
In these examples, the Adapter class or structure transforms the specificRequest method of the Adaptee class or structure into the request method of the Target interface or trait. In this way, the codes using the Target interface or trait can use the features of the Adaptee class or structure through the Adapter.
The Adapter Pattern provides compatibility between two classes or structures and thus enables a class or structure to be transformed into the interface shape expected by another class or structure. This increases the reusability of the code and provides a more flexible design.
These examples demonstrate how the Adapter Pattern can be implemented in different programming languages. Remember that each language has its own characteristics and syntax, so the implementation in each language may be slightly different. However, the basic principles of the Adapter Pattern are the same in every language.
