Skip to content

Commit 128d556

Browse files
committed
done adapter
1 parent dbb7814 commit 128d556

30 files changed

+794
-0
lines changed
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Adapter Structural Design Pattern
2+
Also known as: `Wrapper`
3+
4+
- is a Structural Design Pattern.
5+
- Adapter pattern works as a` bridge between two incompatible interfaces.`
6+
- A construct which adapts an
7+
existing interface X to conform to the required interface Y.
8+
9+
<table>
10+
<tr>
11+
<td><img src="assets/adapter.jpeg"></td>
12+
<td><img src="assets/adapter-diagram.png"><td>
13+
</tr>
14+
<tr>
15+
<td></td>
16+
<td><img src="assets/adapter_explanation.jpg"><td>
17+
</tr>
18+
</table>
19+
20+
- An adapter wraps one of the objects to hide the complexity of conversion happening behind the scenes.
21+
22+
The wrapped object isn’t even aware of the adapter. For example, you can wrap an object that operates in meters and kilometers with an adapter that converts all of the data to imperial units such as feet and miles.
23+
- Sometimes it’s even possible to create a two-way adapter that can convert the calls in both directions.
24+
25+
## Sections
26+
27+
- [Types](#Types)
28+
- [Object Adapter](#Object-Adapter)
29+
- [Class Adapter](#Class-Adapter)
30+
- [How to Implement](#How-to-Implement)
31+
- [Examples](#Examples)
32+
- [square pegs and round holes Example](#square-pegs-and-round-holes-Example)
33+
- [Xml and json](#Xml-and-json)
34+
- [vessel volume Example](#vessel-volume-Example)
35+
- [Example in Arabic with explanation](#Example-in-Arabic-with-explanation)
36+
- [TO DO](#TO-DO)
37+
38+
39+
## Types
40+
<center> `Object Adapter && Class Adapter` </center>
41+
42+
<table>
43+
<tr>
44+
<th>Object Adapter</th>
45+
<th>Class Adapter</th>
46+
</tr>
47+
<tr>
48+
<td>This implementation uses the object composition principle: the adapter implements the interface of one object and wraps the other one. It can be implemented in all popular programming languages.</td>
49+
<td>This implementation uses inheritance: the adapter inherits interfaces from both objects at the same time. Note that this approach can only be implemented in programming languages that support multiple inheritance, such as C++.</td>
50+
</tr>
51+
<tr>
52+
<td><img src="assets/structure-object-adapter.png"></td>
53+
<td><img src="assets/structure-class-adapter.png"></td>
54+
</tr>
55+
<tr>
56+
<td>The Adapter is a class that’s able to work with both the client and the service: (1-it implements the client interface), (2-while wrapping the service object).The adapter receives calls from the client via the adapter interface and translates them into calls to the wrapped service object in a format it can understand.</td>
57+
<td>The Class Adapter doesn’t need to wrap any objects because it inherits behaviors from both the client and the service. The adaptation happens within the overridden methods. The resulting adapter can be used in place of an existing client class.</td>
58+
</tr>
59+
60+
</table>
61+
62+
---
63+
## How to Implement
64+
1. Make sure that you have at least two classes with incompatible interfaces:
65+
1. A useful service class, which you can’t change (often 3rd-party, legacy or with lots of existing dependencies).
66+
1. One or several client classes that would benefit from using the service class.
67+
68+
1. Declare the client interface and describe how clients communicate with the service.
69+
70+
1. Create the adapter class and make it follow the client interface. Leave all the methods empty for now.
71+
72+
1. Add a field to the adapter class to store a reference to the service object. The common practice is to initialize this field via the constructor, but sometimes it’s more convenient to pass it to the adapter when calling its methods.
73+
74+
1. One by one, implement all methods of the client interface in the adapter class. The adapter should delegate most of the real work to the service object, handling only the interface or data format conversion.
75+
76+
1. Clients should use the adapter via the client interface. This will let you change or extend the adapters without affecting the client code.
77+
78+
79+
## Examples
80+
81+
### square pegs and round holes Example
82+
- Example in dart: <a href="square_pegs_and_round_holes/README.md" target="_blank">square pegs and round holes Example </a>
83+
- Example Source: <a href="https://refactoring.guru/design-patterns/adapter" target="_blank">refactoring.guru/design-patterns/adapter</a>
84+
85+
### Xml and json
86+
- Example in dart: <a href="xml_and_json/README.md" target="_blank">Xml and json</a>
87+
- Example Source: <a href="https://www.c-sharpcorner.com/article/adapter-design-pattern/" target="_blank">https://www.c-sharpcorner.com/article/adapter-design-pattern/</a>
88+
89+
### ToyDuck and Bird
90+
- Example in dart: <a href="bird_and_toy_duck/README.md" target="_blank">bird and toy duck</a>
91+
- Example Source: <a href="https://www.geeksforgeeks.org/adapter-pattern/" target="_blank">https://www.geeksforgeeks.org/adapter-pattern/</a>
92+
93+
### Example in Arabic with explanation
94+
- Source: <a href="https://www.linkedin.com/pulse/design-patterns-arabic-7-adapter-hassan-elseoudy/?originalSubdomain=ae" target="_blank">https://www.linkedin.com/pulse/design-patterns-arabic-7-adapter-hassan-elseoudy/?originalSubdomain=ae</a>
95+
96+
97+
## TO DO
98+
99+
- convert sms example to dart
100+
- Example: <a href="sms_example/README.md" target="_blank">sms example</a>
101+
- <a href="https://youtu.be/LP0PZ7WPJPo" target="_blank">https://youtu.be/LP0PZ7WPJPo</a>
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

structural_design_pattern/adapter/assets/toy_duck_and_bird.drawio.svg

+4
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Example: ToyDuck and Bird
2+
3+
- Suppose you have a Bird class with fly(), with makeSound()methods.
4+
- And also a ToyDuck class with squeak() method.
5+
- Let’s assume that you are short on ToyDuck objects and you would like to use Bird objects in their place.
6+
- Birds have some similar functionality but implement a different interface, so we can’t use them directly.
7+
- So we will use adapter pattern. Here our client would be ToyDuck and adaptee would be Bird.
8+
9+
---
10+
Example Source: <a href="https://www.geeksforgeeks.org/adapter-pattern/" target="_blank">https://www.geeksforgeeks.org/adapter-pattern/</a>
11+
12+
13+
## This is how our UML would look:
14+
15+
<img src="../assets/bird_and_duck_toy_diagram.jpg">
16+
<img src="../assets/toy_duck_and_bird.drawio.svg">
17+
18+
## Dart implementation of Adapter pattern
19+
20+
``` dart
21+
abstract class Bird {
22+
// birds implement Bird interface that allows
23+
// them to fly and make sounds adaptee interface
24+
void fly();
25+
void makeSound();
26+
}
27+
28+
// a concrete implementation of bird
29+
class Sparrow implements Bird {
30+
void fly() => print("Flying");
31+
void makeSound() => print("Chirp Chirp");
32+
}
33+
34+
abstract class ToyDuck {
35+
// target interface
36+
// toyducks dont fly they just make
37+
// squeaking sound
38+
void squeak();
39+
}
40+
41+
class PlasticToyDuck implements ToyDuck {
42+
void squeak() => print("Squeak");
43+
}
44+
45+
class BirdAdapter implements ToyDuck {
46+
// You need to implement the interface your
47+
// client expects to use.
48+
Bird bird;
49+
50+
// we need reference to the object we
51+
// are adapting
52+
BirdAdapter(Bird this.bird);
53+
54+
// translate the methods appropriately
55+
@override
56+
void squeak() => bird.makeSound();
57+
}
58+
59+
void main() {
60+
Sparrow sparrow = Sparrow();
61+
ToyDuck toyDuck = PlasticToyDuck();
62+
63+
// Wrap a bird in a birdAdapter so that it
64+
// behaves like toy duck
65+
ToyDuck birdAdapter = BirdAdapter(sparrow);
66+
67+
print("Sparrow...");
68+
sparrow.fly();
69+
sparrow.makeSound();
70+
71+
print("ToyDuck...");
72+
toyDuck.squeak();
73+
74+
// toy duck behaving like a bird
75+
print("BirdAdapter...");
76+
birdAdapter.squeak();
77+
}
78+
```
79+
## Output
80+
81+
Sparrow...
82+
Flying
83+
Chirp Chirp
84+
ToyDuck...
85+
Squeak
86+
BirdAdapter...
87+
Chirp Chirp
88+
89+
90+
## Explanation
91+
- Suppose we have a `bird` that can makeSound(),
92+
- and we have a `plastic toyDuck` that can squeak().
93+
- Now suppose our client changes the requirement and he wants the toyDuck to makeSound
94+
- than ? Simple solution is that we will just change the implementation class to the adapter class and tell the client to pass the instance of the bird(which wants to squeak()) to that class.
95+
96+
Before : ToyDuck toyDuck = PlasticToyDuck();
97+
After : ToyDuck toyDuck = BirdAdapter(sparrow);
98+
You can see that by changing just one line the toyDuck can now do Chirp Chirp !!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Example:
2+
// Suppose you have a Bird class with fly() ,
3+
// and makeSound()methods.
4+
// And also a ToyDuck class
5+
// with squeak() method.
6+
// Let’s assume that you are short on ToyDuck objects
7+
// and you would like to use Bird objects in their place.
8+
// Birds have some similar functionality but implement a different interface,
9+
// so we can’t use them directly.
10+
// So we will use adapter pattern.
11+
// Here our client would be ToyDuck and adaptee would be Bird.
12+
13+
// Dart implementation of Adapter pattern
14+
// source:: https://www.geeksforgeeks.org/adapter-pattern/
15+
16+
abstract class Bird {
17+
// birds implement Bird interface that allows
18+
// them to fly and make sounds adaptee interface
19+
void fly();
20+
void makeSound();
21+
}
22+
23+
// a concrete implementation of bird
24+
class Sparrow implements Bird {
25+
void fly() => print("Flying");
26+
void makeSound() => print("Chirp Chirp");
27+
}
28+
29+
abstract class ToyDuck {
30+
// target interface
31+
// toyducks dont fly they just make
32+
// squeaking sound
33+
void squeak();
34+
}
35+
36+
class PlasticToyDuck implements ToyDuck {
37+
void squeak() => print("Squeak");
38+
}
39+
40+
class BirdAdapter implements ToyDuck {
41+
// You need to implement the interface your
42+
// client expects to use.
43+
Bird bird;
44+
45+
// we need reference to the object we
46+
// are adapting
47+
BirdAdapter(Bird this.bird);
48+
49+
// translate the methods appropriately
50+
@override
51+
void squeak() => bird.makeSound();
52+
}
53+
54+
void main() {
55+
Bird sparrow = Sparrow();
56+
ToyDuck toyDuck = PlasticToyDuck();
57+
58+
// Wrap a bird in a birdAdapter so that it
59+
// behaves like toy duck
60+
ToyDuck birdAdapter = BirdAdapter(sparrow);
61+
62+
print("Sparrow...");
63+
sparrow.fly();
64+
sparrow.makeSound();
65+
66+
print("ToyDuck...");
67+
toyDuck.squeak();
68+
69+
// toy duck behaving like a bird
70+
print("BirdAdapter...");
71+
birdAdapter.squeak();
72+
}
73+
74+
// Output:
75+
76+
// Sparrow...
77+
// Flying
78+
// Chirp Chirp
79+
// ToyDuck...
80+
// Squeak
81+
// BirdAdapter...
82+
// Chirp Chirp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="app.diagrams.net" modified="2022-03-22T23:58:43.927Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.46" etag="-yQQP4eiU_0fDsAhoVIs" version="17.1.3" type="device"><diagram name="Page-1" id="9f46799a-70d6-7492-0946-bef42562c5a5">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</diagram></mxfile>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
namespace App\Patterns\Structural\Adapter\SMSAdapter\Adapters\ABCSMSManager;
3+
4+
class SMSManager
5+
{
6+
public function send(array $messages)
7+
{
8+
if($this->checkConnection() && $this->authenticate() && $this->connect()) {
9+
foreach ($messages as $message) {
10+
echo "Your message {$message['text']} is being sent to {$message['number']}'\n";
11+
}
12+
}
13+
}
14+
15+
public function connect(): bool
16+
{
17+
return true;
18+
}
19+
20+
public function checkConnection(): bool
21+
{
22+
return true;
23+
}
24+
25+
public function authenticate(): bool
26+
{
27+
return true;
28+
}
29+
30+
public function validatePhoneNumber(string $phoneNumber): bool
31+
{
32+
return strlen($phoneNumber) < 8;
33+
}
34+
35+
public function getDeliveryStatus(): string
36+
{
37+
return rand(5,8);
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
namespace App\Patterns\Structural\Adapter\SMSAdapter\Adapters;
3+
4+
use App\Patterns\Structural\Adapter\SMSAdapter\Adapters\ABCSMSManager\SMSManager;
5+
use App\Patterns\Structural\Adapter\SMSAdapter\Messages\Message;
6+
use App\Patterns\Structural\Adapter\SMSAdapter\SMSClient;
7+
use App\Patterns\Structural\Adapter\SMSAdapter\SMSDeliveryStatus;
8+
9+
class ABSSMSClientAdapter extends SMSClient
10+
{
11+
private ?SMSManager $manager = null;
12+
13+
public function __construct(array $messages = [])
14+
{
15+
parent::__construct($messages);
16+
$this->manager = new SMSManager();
17+
}
18+
19+
public function filterNumbers(): bool
20+
{
21+
$this->messages = array_filter(
22+
$this->messages,
23+
fn (Message $message) => $this->manager->validatePhoneNumber($message->getNumber())
24+
);
25+
return !empty($this->messages);
26+
}
27+
28+
public function send(): bool
29+
{
30+
if($this->filterNumbers()) {
31+
$this->manager->send(
32+
array_map(function (Message $message): array {
33+
return [
34+
'number' => $message->getNumber(),
35+
'text' => $message->getMessage()
36+
];
37+
}, $this->messages)
38+
);
39+
}
40+
return $this->getDeliveryStatus() === SMSDeliveryStatus::SENT;
41+
}
42+
43+
public function getDeliveryStatus(): string
44+
{
45+
return $this->manager->getDeliveryStatus() - 4;
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
namespace App\Patterns\Structural\Adapter\SMSAdapter\Messages;
3+
4+
interface Message
5+
{
6+
public function getMessage(): string;
7+
public function getNumber(): string;
8+
public function validateMessage(): bool;
9+
public function validateNumber(): bool;
10+
}

0 commit comments

Comments
 (0)