PHP Design Patterns

Post Title

 1. Ce sunt Design Patterns ? 

       Design Patterns pot fi privite ca solutii propuse pentru a putea evita anumite      probleme intalnite in programarea orientata pe obiecte, aceste solutii pot fi    implementate in orice limbaj insa eu ma voi referi strict la PHP. 

 Obs. Sa nu credeti ca nu pot fi implementate aceste solutii si in programarea  procedurala, insa avantajul major este observat in OOP

 

 

2. Ce probleme rezolva Desing Patterns ? 

1. Consumul de resurse

2. Ordonarea si incapsularea codului

3. Separarea logici de output-ul site-ului

 

Acestea sunt doar cateva din avantajele accestor solutii.

3. Cele mai folosite Desing Paterns

Mai jos o prezint cele mai folosite solutii in oop, asadar voi incepe cu :

 

3.1 Singleton

        Acest pattern este unul din cel mai simple iar conceptul sau spune ca permite acces la o singura resursa, iar aceasta nu va fi niciodata duplicata. Foarte important e ca aceasta resursa trebuie sa poata fi acesata oricand si oriunde. 

        De asemnea acesta solutie prevede o modalitate de a acesa clasa fara a crea un obiect al acesteia, toate astea referindu-ne la Singleton pur.

        Pentru a putea crea o astfel de clasa va trebuie sa facem constructorul privat ( poate o sa vi se para aiurea dar este necesar), pentru a nu se putea crea o instanta a clasei prin new ceea ce e foarte important, deoarece vom folosi operatorul de rezolutie :: pentru a accesa continutul clasei, mai jos o sa dau un exemplu pentru o clasa masina.

  1.  
  2. <?php
  3.  
  4. class Masina {
  5. private static $_masina;
  6. private $motor, $putere, $masina;
  7.  
  8. private function __construct() {
  9. $this->motor = 1.0;
  10. $this->putere = '20cp';
  11. $this->masina = 'golf';
  12. }
  13.  
  14. public static function Instanta() {
  15. //Daca nu exista o instanta a clasei
  16. if(!self::$_masina) {
  17. //creem una
  18. self::$_masina = new Masina();
  19. echo "__Instanta creata___<br />";
  20. } else {
  21. echo "__Instanta este deja creata___<br />";
  22. }
  23. //returnam instanta
  24. return self::$_masina;
  25. }
  26.  
  27. public function daMasina() {
  28. echo $this->motor. ' '.$this->putere.' '.$this->masina."<br />";
  29. }
  30.  
  31. }
  32.  
  33. Masina::Instanta()->daMasina();
  34. Masina::Instanta()->daMasina();
  35. Masina::Instanta()->daMasina();
  36.  
  37. ?>

Iar outputul este :

 
__Instanta creata___
1 20cp golf
__Instanta este deja creata___
1 20cp golf
__Instanta este deja creata___
1 20cp golf

        Ce e important sa integeti e ca daca clasa nu este instantiata se creaza o instanta daca are una va fi folosita(codul important este in metoda Instanta), probabil o sa intrebati si la ce bun, ei bine uneori doriti sa existe o singura instanta de exemplu daca ar fi o clasa de conexiune la o baza de date, si in contructor ar fi conexiunea, nu ar fi ok sa existe o singura conexiune? nu 100 de conexiuni la baza de date?

        Cu toate ca e cel mai simplu cred ca deja ati realizat cat e de folositor, un exemplu e mai sus cel cu baza de date + de asta uneori nu e nevoie de 10 instantieri sau obiecte, iar daca scriem mult cod apar si erorile in logica astfel ne salvam pe noi de la a consuma memorie in plus, doarece fiecare instantiere este tinuta in memorie.

3.2 Registry

Mai sus am discutat despre Singleton, dar ce se intampla daca am nevoie sa imi instantiez de mai multe ori clasa? stiu ca cu Singleton se poate o singura data, daca vreau 2 conexiuni catre 2 baze de date diferite de exemplu? Atunci vine modelul Registry in ajutorul vostru, el fiind un "Singleton " ce permite instantiere multipla, dar controlata.

  1.  
  2. <?php
  3.  
  4. class Masina {
  5.  
  6. private static $_masina = array();
  7. private $motor, $putere, $masina;
  8.  
  9. private function __construct() {
  10.  
  11. }
  12.  
  13. public static function creazaInstanta($nume){
  14. if (isset(self::$_masina[$nume])) {
  15. throw new Exception("Exista deja o instatiere pe acest nume");
  16. } else {
  17. self::$_masina[$nume] = new Masina();
  18. }
  19. }
  20.  
  21. public static function daInstanta($nume) {
  22. //Daca nu exista o instanta a clasei
  23. if(!isset(self::$_masina[$nume])) {
  24. throw new Exception("Acceasta instanta nu exista");
  25. } else {
  26. echo "__Instanta ".$nume." este returnata___<br />";
  27. return self::$_masina[$nume];
  28. }
  29. }
  30. }
  31.  
  32. Masina::creazaInstanta("Golf");
  33. Masina::creazaInstanta("Passat");
  34. Masina::daInstanta("Golf");
  35. Masina::daInstanta("Passat");
  36.  
  37. ?>

 

Rezultatul fiind : 

 
__Instanta Golf este returnata___
__Instanta Passat este returnata___

 

Accest model poate fi imbunatatit, de exemplu sa stocheze instante ale altor clase, daca aveti intrebari va rog sa lasati comentarii.

3.3 Factory

 

        

       

      Daca o luam babeste dupa nume, din start ne dam sema ca acest pattern "fabrica" ceva, o clasa care "fabrica" alte clase, e aiurea spus dar chiar asta face, Factory este gandit ca o clasa generala care instantiaza alte clase in interioriul ei, dar nu orice clase ci clase care se ocupa de acelasi lucru, sa zicem ca primim de la un api date atat in format json cat si xml, iar noi avem o singura clasa numita Interpretare, in interiorul ei instantiem alte doua clase pasrseXml si parseJson, partea frumoasa aici este ca noi defapt creem si returnam un obiect, dar asta o sa intelegeti mai bine din exemplele urmatoare.

  1.  
  2.  
  3.  
  4.  
  5. class parseazaJson {}
  6. class parseazaXml {}
  7. class Interpreteaza {
  8.  
  9. const JSON = 1 ;
  10. const XML = 2 ;
  11.  
  12. public static function parseRes($type = self::JSON) {
  13. switch (trim((int)$type)) {
  14. case 1:
  15. return new parseazaJson();
  16. break;
  17. case 2:
  18. return new parseazaXml();
  19. break;
  20. default:
  21. throw new Exception('Clasa poate parsa doar xml si json');
  22. }
  23. }
  24. }
  25.  
  26. $parse = Interpreteaza::parseRes(Interpreteaza::XML);
  27. var_export($parse);

Iar rezultatul va fi

 
parseazaXml::__set_state(array( ))

 

       De aici ne putem da seama ce inseamna modelul Factory prin clasa noastra am initializat alta clasa, spre deosebire de singleton nu am fost nevoiti sa face constructorul privat. Ce trebuie sa intelegeti voi e ca prin modelul Factory o clasa generala initializeaza alte clase care se ocupa cu acelasi lucru, acum o sa va prezint cateva trucuri frumoase in Factory:

ex:  1.

In mod normal noi creem un obiect apoi apelam o metoda care dorim prin urmatorul set de instructiuni

  1.  
  2. <?php
  3. $ob = new NumeClasa();
  4. $ob->metoda();
  5. ?>

In factory putem sa facem totul cu o singura line :

  1.  
  2. <?php
  3. class NumeClasa {
  4. public static function factory() {
  5. return new NumeClasa();
  6. }
  7. public function metoda() {
  8. echo 'Apelare metoda prin factory pattern';
  9. }
  10. }
  11.  
  12. NumeClasa::factory()->metoda();
  13. ?>

ex 2 :

Avand in vedere ca Factory initializeaza alte clase prin clasa noastra generala, am putea sa dam noi clasa care dorim sa o initializam ca un parametru pentru o metoda Factory.

  1.  
  2. <?php
  3. class WebSite {};
  4. class Factory
  5. {
  6. public static function instance($nameClass = null)
  7. {
  8. if($nameClass)
  9. return new $nameClass;
  10. else
  11. return false;
  12. }
  13. }
  14.  
  15. $web = Factory::instance("WebSite");
  16. var_export($web);
  17. ?>

              Iar outputul este 

 
WebSite::__set_state(array( ))

             Asadar am creat o instanta a clasei WebSite prin clasa Factory

 

3.4 MVC

       

Sunt sigur ca majoritatea ati auzit de MVC, majoritatea framework-urilor si CMS-urilor actuale sunt scrise in MVC.

MVC-ul este cu mult mai complex decat modelele anterioare, el prevede 3 parti un model un controller si un view. 

1. Controller-ul sau partea decizionala este prima apelata si va decide ce va face cu requestul primit

 

 2. Model-ul, este apelat de catre controller, si se ocupa de logica adica interogari din baza de date, care le va returna controller-ului.

 

3. View primeste datele prelucrate de controller care pot fi afisate utilizatorului.

 

        Aplicatiile pe acest model sunt foarte organizate, se pot exinde si se poate face debug-ing foarte usor pe ele. Mai jos o sa dau un scurt exemplu de MVC

  1.  
  2. <?php
  3. //controller
  4.  
  5. Class Controller {
  6. private $model,$view;
  7. public function decide( $info = null ) {
  8. $this->model = new Model();
  9. $this->view = new View();
  10. if ($this->model->get($info)) {
  11. $this->view->afiseaza("Bun venit pe micul-programator, Username");
  12. } else {
  13. $this->view->eroare(array(
  14. 'cod' => 1 ,
  15. 'mesaj' => 'Acest utilizator nu exista',
  16. ));
  17. }
  18. }
  19.  
  20. }
  21.  
  22. Class Model {
  23.  
  24. public function get( $id ) {
  25. //aici ar trebui sa fie un query
  26. if( $id == 1 )
  27. return true;
  28. else
  29. return false;
  30. }
  31.  
  32. }
  33.  
  34. Class View {
  35.  
  36. public function afiseaza ($date) {
  37. echo "Controllerul zice ca trebuie sa afisez ".$date;
  38. }
  39.  
  40. public function eroare($date) {
  41. print_r($date);
  42. }
  43.  
  44. }
  45.  
  46. $obj = new Controller();
  47. $obj->decide($_GET['user']);
  48.  
  49. ?>

 

Daca : index?user=1

 
Controllerul zice ca trebuie sa afisez Bun venit pe micul-programator, Username

Daca :  index?user=2

 
Array ( [cod] => 1 [mesaj] => Acest utilizator nu exista )

        Modelul este mult mai complex decat ce am prezentat eu mai sus, eu am incercat sa fac ceva cat se poate de simplu, acest model trebuie privit la nivel de fisiere si directore, pentru a va da mai bine seama va recomand sa va uitati in core la un framework sau un cms MVC. 

Mai sunt si alte design patterns insa acceste sunt cele mai folosite sau cel putin asa ma gasit eu, ar ma fi

1 . Strategy

2. Observer

3. chain-of-command 

 

Aici se termina acest tutorial, sper sa va fie de folos, un an nou cu bine wink

Autor articol

Ştiinţa fără religie este şchioapă, religia fără ştiinţă este oarbă (Albert Einstein)

Articolul anterior


Comentarii

Comentariu adaugat de marian
Chiar mi-as dori sa pot scrie mai mult dar timpul meu este foarte limitat, dar promit sa sa mai scriu printre picaturi :P
go to page top marian | 2014-03-11
Comentariu adaugat de GarryOne
Bravo. Foarte util tutorialul. Te asteptam cu cat mai multe tutorialele pe asemenea teme, si anume, tehnici avansate si optimizate de programare.
go to page top GarryOne | 2014-03-10
Comentariu adaugat de marian
Si eu sper asta, sa am timp sa scriu cat mai multe chestii, din pacate unul din editori (Adelin) are in vara un examen foarte important la care trebuie sa se pregatesca intens, insa Ciprian a promis ca revine in forta, cat despre mine, voi incerca sa scriu anul accesta cat mai multe articole. 

Ma bucur ca iti place tema actuala, astept activitate si din partea voastra, articolele devin mai interesante daca sunt comentate 
go to page top marian | 2014-01-04
Comentariu adaugat de danutz0501
Din ce in ce mai interesante articolele, bun asa si designul sitului destul de interesant.

Personal sper ca tu si echipa ta sa aveti mai mult timp de tutoriale
go to page top danutz0501 | 2014-01-04

Exista 4 comentarii   

  • 1
Trebuie sa fii logat sa poti lasa un comentariu Autentificare Inregistrare Logare cu Facebook
top