Skip to content

Commit 4dfd9c1

Browse files
Added new Adapter Pattern
1 parent 93470c3 commit 4dfd9c1

File tree

3 files changed

+210
-1
lines changed

3 files changed

+210
-1
lines changed

content/Adapter Pattern.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
title: Abstract Factory Pattern
3+
created: 2025-07-30
4+
tags:
5+
- structural
6+
---
7+
## Definition
8+
9+
The Adapter Pattern converts the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
10+
11+
---
12+
## Real World Analogy
13+
14+
Imagine you bought a machine from China and imported it to India. The problem is that the plugs and sockets used in China are totally different from those in India. You still need to power on the machine, but you can’t simply connect it directly to the Indian socket.
15+
16+
Here the adapter comes into play. Instead of cutting wires and reattaching them to an Indian plug, you can use an adapter that converts the Chinese plug to fit the Indian socket.
17+
18+
![[adapter_workflow.png]]
19+
_Example of the Adapter Pattern to use a China plug with an Indian socket board._
20+
21+
Similarly, in our code example we have a `Duck` interface and implementations from the [[Strategy Pattern]]. We want to add a new bird type, `Turkey`, but also use the existing `Duck` interface without changing any existing code. As the [[#Definition]] says, we can translate one interface to another without touching the existing implementations. Here, we’ll adapt the `Turkey` to behave like a `Duck`.
22+
23+
---
24+
## Design
25+
26+
```mermaid
27+
classDiagram
28+
%% Interfaces
29+
class Duck {
30+
<<interface>>
31+
+fly()
32+
+quack()
33+
}
34+
class Turkey {
35+
<<interface>>
36+
+fly()
37+
+run()
38+
}
39+
40+
%% Concrete classes
41+
class MallardDuck {
42+
+fly()
43+
+quack()
44+
}
45+
class WildTurkey {
46+
+fly()
47+
+run()
48+
}
49+
class TurkeyAdapter {
50+
-turkey: Turkey
51+
+TurkeyAdapter(turkey: Turkey)
52+
+fly()
53+
+quack()
54+
}
55+
56+
%% Relationships
57+
Duck <|.. MallardDuck
58+
Turkey <|.. WildTurkey
59+
TurkeyAdapter ..|> Duck
60+
TurkeyAdapter --> Turkey : adapts
61+
```
62+
63+
_Design diagram showing how `TurkeyAdapter` adapts a `Turkey` to the `Duck` interface._
64+
65+
---
66+
## Implementation In Java
67+
68+
Firstly, let’s look at the existing `Duck` interface and its `MallardDuck` implementation.
69+
70+
```java title="Duck.java"
71+
interface Duck {
72+
public void fly();
73+
public void quack();
74+
}
75+
```
76+
77+
```java title="MallardDuck.java"
78+
class MallardDuck implements Duck {
79+
80+
@Override
81+
public void fly() {
82+
System.out.println("Mallard Duck Flying");
83+
}
84+
85+
@Override
86+
public void quack() {
87+
System.out.println("Mallard Duck quacking");
88+
}
89+
90+
}
91+
```
92+
The `Duck` interface defines two methods: `fly()` and `quack()`. `MallardDuck` implements these methods, providing the concrete behavior for a normal duck.
93+
94+
Next, we define the `Turkey` interface and its implementation:
95+
96+
```java title="Turkey.java"
97+
interface Turkey {
98+
public void fly();
99+
public void run();
100+
}
101+
```
102+
103+
```java title="WildTurkey.java"
104+
class WildTurkey implements Turkey {
105+
106+
@Override
107+
public void fly() {
108+
System.out.println("Turkey Flying");
109+
}
110+
111+
@Override
112+
public void run() {
113+
System.out.println("Turkey Running");
114+
}
115+
116+
}
117+
```
118+
The `Turkey` interface has two methods: `fly()` and `run()`. `WildTurkey` provides concrete behavior for these methods.
119+
120+
Since `Turkey` does not have a `quack()` method, we create an adapter to translate a `Turkey` into a `Duck`:
121+
122+
```java title="TurkeyAdapter.java"
123+
class TurkeyAdapter implements Duck {
124+
private Turkey turkey;
125+
126+
public TurkeyAdapter(Turkey turkey) {
127+
this.turkey = turkey;
128+
}
129+
130+
@Override
131+
public void fly() {
132+
// Delegate the fly call to the turkey
133+
this.turkey.fly();
134+
}
135+
136+
@Override
137+
public void quack() {
138+
// Since turkeys don't quack, delegate quack to run()
139+
this.turkey.run();
140+
}
141+
}
142+
```
143+
`TurkeyAdapter` implements the `Duck` interface. It holds a reference to a `Turkey` object and delegates `fly()` calls directly, while `quack()` calls are mapped to the turkey’s `run()` method.
144+
145+
Finally, we put everything together:
146+
147+
```java title="ObjectAdapterDemo.java"
148+
public class ObjectAdapterDemo {
149+
public static void main(String[] args) {
150+
// Original Duck
151+
Duck duck = new MallardDuck();
152+
// Adapted Turkey
153+
Duck duck2 = new TurkeyAdapter(new WildTurkey());
154+
155+
duck.quack();
156+
duck2.quack();
157+
}
158+
}
159+
```
160+
*Output:*
161+
```text
162+
Mallard Duck quacking
163+
Turkey Running
164+
```
165+
---
166+
## Class Adapter
167+
168+
The above example uses the **Object Adapter** approach. You can also implement a **Class Adapter** when the language supports multiple inheritance. Java does not allow multiple class inheritance, but you can achieve similar behavior using multiple interfaces. In languages like C++, you could directly inherit both the target interface and the adaptee.
169+
170+
---
171+
## Real World Example
172+
173+
A classic example in Java is `InputStreamReader`:
174+
```java title="InputStreamExample.java"
175+
public static void main(String[] args) throws FileNotFoundException, IOException {
176+
String path = System.getProperty("user.dir");
177+
path = path.concat("/src/adapter/file.txt");
178+
179+
File file = new File(path);
180+
// Adaptee: byte-based API
181+
InputStream fileStream = new FileInputStream(file);
182+
// Adapter: converts bytes to characters
183+
Reader inputStreamReader = new InputStreamReader(fileStream);
184+
// Client: reads text lines
185+
BufferedReader reader = new BufferedReader(inputStreamReader);
186+
String line;
187+
while ((line = reader.readLine()) != null) {
188+
System.out.println(line);
189+
}
190+
reader.close();
191+
}
192+
```
193+
**Why it is called an Adapter?**
194+
1. **Adaptee**: `InputStream` (byte‐based API).
195+
2. **Target Interface**: `Reader` (char‐based API that many APIs expect).
196+
3. **Adapter**: `InputStreamReader` extends `Reader` and internally holds an `InputStream`, delegating calls and translating bytes into characters.
197+
198+
Whenever you need to feed a `byte[]`, a `Socket.getInputStream()`, or a `FileInputStream` into a component that only accepts a `Reader`, you’re using the Adapter Pattern—straight out of the core Java I/O library.
199+
200+
---
201+
## Design Principles:
202+
203+
- **Encapsulate What Varies** - Identify the parts of the code that are going to change and encapsulate them into separate class just like the Strategy Pattern.
204+
- **Favor Composition Over Inheritance** - Instead of using inheritance on extending functionality, rather use composition by delegating behavior to other objects.
205+
- **Program to Interface not Implementations** - Write code that depends on Abstractions or Interfaces rather than Concrete Classes.
206+
- **Strive for Loosely coupled design between objects that interact** - When implementing a class, avoid tightly coupled classes. Instead, use loosely coupled objects by leveraging abstractions and interfaces. This approach ensures that the class does not heavily depend on other classes.
207+
- **Classes Should be Open for Extension But closed for Modification** - Design your classes so you can extend their behavior without altering their existing, stable code.
208+
- **Depend on Abstractions, Do not depend on concrete class** - Rely on interfaces or abstract types instead of concrete classes so you can swap implementations without altering client code.
103 KB
Loading

content/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ created: 2025-02-07
77
**Design patterns** are typical solutions to commonly occurring problems in software design. They are like pre-made blueprints that you can customize to solve a recurring design problem in your code.
88
## Three Main Patterns
99

10-
- **Creational patterns** provide object creation mechanisms that increase flexibility and reuse of existing code.
10+
- **Creational patterns** provide object creation mechanisms that increase flexibility and reuse of existing code. #creational
1111
- **Structural patterns** explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient. #structural
1212
- **Behavioral patterns** take care of effective communication and the assignment of responsibilities between objects. #behavioral
1313

@@ -124,6 +124,7 @@ Consider an `SQLManager` class that performs CRUD operations. It has an `ILogger
124124
5. [[Abstract Factory Pattern]]
125125
6. [[Singleton Pattern]]
126126
7. [[Command Pattern]]
127+
8. [[Adapter Pattern]]
127128

128129
---
129130
> [!Note]

0 commit comments

Comments
 (0)