Advertisement
  1. Code
  2. Coding Fundamentals
  3. OOP

Design Pattern-uri: Modelul de tip "Adaptor"

Scroll to top
Read Time: 5 min
This post is part of a series called Design Patterns in PHP.
Design Patterns: The Facade Pattern
Design Patterns: The Decorator Pattern

() translation by (you can also view the original English article)

In acest ultim articol, am adus in discutie modul in care design pattern-ul de tip "Fatada" (Facade) poate fi inclus pentru a simplifica integrarea oricarui sistem oricat de complex folosind doar o clasa de tip "Fatada".

In articolul de fata vom continua discutia noastra asupra design pattern-urilor aruncand o privire asupra modelului de tip "Adaptor". Acest model particular poate fi folosit atunci cand codul vostru depinde de API-uri externe sau orice alta clasa predispusa schimbarilor frecvente. Acest model face parte din categoria "modelelor structurale" deoarece ne invata modul in care codul si clasele noastre trebuie structurate pentru a le putea organiza si/sau extinde cu usurinta.

Din nou, as vrea sa readuc in discutie faptul ca design pattern-urile nu aduc nimic nou fata de clasele traditionale. In schimb, ne ajuta sa intelegem mai bine modul in care trebuie sa ne structuram clasele, cum putem manipula comportamentul lor si cum putem organiza crearea acestor clase.

Problema

1
class Twitter {
2
3
  public function __construct() {
4
		// Codul vostru //

5
	}
6
7
	public function send($msg) {
8
		// Postarea catre Twitter //

9
		echo $msg;
10
	}
11
}
12
13
$twitter = new Twitter();
14
$twitter->send('Posting on Twitter');

In codul de mai sus, puteti vedea ca utilizam o clasa Twitter doar pentru a trimite un mesaj. Aici cream direct obiectul API Twitter si postam mesajele pe Twitter. Aveti acest cod duplicat in mai multe locuri. Putem vedea ca in cod este folosita metoda $twitter->send('Posting on Twitter'); pentru a trimite mesajele.

Cu ceva timp in urma, Twitter a schimbat numele metodei din API din send in sendTweet. Aceasta ar trebui in mod clar sa ridice o problema pentru aceia dintre noi care au folosit metoda send. Mai exact, avem nevoie sa modificam toate apelarile metodei send in sendTweet. Imaginati-va cat cod trebuie schimbat si timpul necesar retestarii fiecarei functionalitati in parte.

Solutia

Una din solutiile acestei probleme este sa folosim un design pattern de tip adaptor.

Potrivit Wikipedia:

In ingineria software, modelul de tip adaptor este un design pattern menit sa traduca interfata unei clase externe intr-o interfata stabila codului existent. Acesta este adesea folosit pentru a integra clase existente cu altele fara a modifica codul existent.

In acest caz, am avea nevoie sa cream o interfata de tip wrapper care face posibil acest lucru. Nu vom face nicio modificare in libraria externa pentru ca nu avem control asupra ei si poate fi modificata oricand.

Sa exploram codul si sa vedem modelul adaptor in actiune:

1
// Exemplificarea implementarii clasei Twitter

2
class Twitter {
3
4
	public function __construct() {
5
		// Codul vostru //

6
	}
7
8
	public function send($msg) {
9
		// Postarea catre Twitter //

10
		echo $msg;
11
	}
12
}
13
14
// Interfata simpla pentru fiecare Adaptor creat

15
interface socialAdapter {
16
	public function send($msg);
17
}
18
19
class twitterAdapter implements socialAdapter {
20
21
	private $twitter;
22
23
	public function __construct(Twitter $twitter) {
24
		$this->twitter = $twitter;
25
	}
26
27
	public function send($msg) {
28
		$this->twitter->send($msg);
29
	}
30
}

Analizati secventa de cod de mai sus si ar trebui sa observati ca nu am introdus nicio modificare in clasa principala Twitter. In schimb am creat o interfata pentru adaptorul nostru si o clasa adaptor pentru Twitter.

Astfel am creat o instanta a clasei adaptor in locul clasei principale Twitter. Instanta clasei adaptor va primi ca argument instanta clasei principale Twitter, in asa fel incat clasa adaptor sa aiba o referinta a acesteia si sa poata apela metodele necesare din clasa Twitter.

Sa aflam cum putem utiliza aceasta metoda in mod direct:

1
// Cod client

2
$twitter = new twitterAdapter(new Twitter());
3
$twitter->send('Posting to Twitter');

Acum imaginati-va ca Twitter schimba numele metodei din send in sendTweet. In acel moment va trebui sa modificam doar in clasa twitterAdapter. Sa aruncam o privire asupra codului revizuit din clasa adaptor care vine doar cu o modificare:

1
class twitterAdapter implements socialAdapter {
2
3
	private $twitter;
4
5
	public function __construct(Twitter $twitter) {
6
		$this->twitter = $twitter;
7
	}
8
9
	public function send($msg) {
10
		$this->twitter->sendTweet($msg);
11
	}
12
}

Deci, cu o singura modificare am terminat.

Adaugarea unui nou Adaptor

In acest moment am vazut cum putem folosi design pattern-ul de tip adaptor pentru a depasi scenariile mentionate mai sus. Acum este foarte usor sa adaugam o noua clasa dependenta de adaptorul existent. Sa spunem ca se doreste actualizarea statusului direct din API-ul de Facebook.

In loc sa ne folosim in mod direct de clasa Facebook putem sa aplicam acelasi model adaptor pe care l-am folosit si pentru Twitter.

1
// Exemplificarea implementarii clasei Facebook

2
class Facebook {
3
4
public function __construct() {
5
		// Codul vostru //

6
	}
7
8
	public function updateStatus($msg) {
9
		// Postarea catre Facebook //

10
		echo $msg;
11
	}
12
}
13
14
// Adaptorul Facebook

15
class facebookAdapter implements socialAdapter {
16
17
	private $facebook;
18
19
	public function __construct(Facebook $facebook) {
20
		$this->facebook = $facebook;
21
	}
22
23
	public function send($msg) {
24
		$this->facebook->updateStatus($msg);
25
	}
26
}
27
28
29
// Cod client

30
$facebook = new facebookAdapter(new Facebook());
31
$facebook->send('Posting to Facebook');

Dupa cum puteti vedea, se aplica acelasi principiu. Definiti o metoda disponibila claselor externe si in cazul in care unul din serviciile dependente face modificari in API-ul lui doar modificati clasa dependenta fara a afecta interfata sa externa.

Concluzii

O aplicatie de mari dimensiuni depinde constant de librarii si API-uri externe, asa ca eu as propune sa implementam metoda "Adaptor" in asa fel incit sa nu fim nevoiti sa ne confruntam cu problemele aduse de modificarile acestor librarii sau API-uri la nivel de cod.

Am incercat cat am putut de bine sa dau un exemplu simplu si in acelasi timp util pentru a demonstra design pattern-ul de tip "Adaptor", dar daca aveti alte comentarii sau intrebari nu ezitati va rog sa mi le adresati in feed-ul de mai jos.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.