Factory method design patten in PHP

Read this post in English

Share on:

Un design patten creational care reprezinta o solutie pentru a genera obiecte fara sa se specifice clasa acestuia. In mod particular orice metoda care genereaza obiecte reprezinta o implementare de Factory Method pattern.

Motivatie:

O motivatie este ca, sarcina de a creea obiectul este delegata catre metoda factory.

Diagrama:

factory method pattern

Implementare:
Clasele care genereaza obiecte prin factory, clasa comuna care va fi extinsa si clasa cu metoda fatory:

  1// clasa comuna care va fi extinsa
  2abstract class OutputBase {
  3     // output headerele necesare
  4     abstract public function header();
  5
  6     // corpul rezultat
  7     abstract public function body($data);
  8
  9}
 10
 11// clasa pentru output xml
 12class XMLOutput extends OutputBase {
 13
 14     // output header xml
 15     public function header() {
 16          header('content-type: text/xml');
 17     }
 18
 19     // document xml
 20     public function body($data) {
 21          $res = '';
 22
 23          $res .= '';
 24
 25          foreach ($data as $root => $item) {
 26
 27               $res .= '';
 28
 29               foreach ($item as $key => $val) {
 30                    $res .= '<'.$key.'>'.$val.'';
 31               }
 32
 33               $res .= '';
 34          }
 35
 36          $res .= '';
 37
 38          return $res;
 39
 40     }
 41
 42}
 43
 44// clasa pentru output csv
 45class CSVOutput extends OutputBase {
 46
 47     // output header csv
 48     public function header() {
 49          header("Content-type: text/plain");
 50     }
 51
 52     // corp csv
 53     public function body($data) {
 54          $res = '';
 55
 56          $keys = array_keys($data[0]);
 57
 58          foreach ($keys as $key) {
 59               $res .= '"'.$key.'";';
 60          }
 61          $res .= "\r\n";
 62
 63          foreach ($data as $item) {
 64               foreach ($item as $val) {
 65                    $res .= '"'.$val.'";';
 66               }
 67
 68               $res .= "\r\n";
 69          }
 70
 71          return $res;
 72     }
 73}
 74
 75// clasa cu metoda factory
 76// este abstracta pentru a nu fi instantiata
 77abstract class OutputFactory {
 78
 79     // constanta pentru timpul xml
 80     const XML = 1;
 81
 82     // constanta pentru tipul csv
 83     const CSV = 2;
 84
 85     // metoda statica factory
 86     public static function getInstance($type) {
 87          // in functie de constanta primita ca parametru
 88          // va intoarce unul din obiecte
 89          switch ($type) {
 90               case self::XML :
 91                    return new XMLOutput();
 92               break;
 93
 94               case self::CSV :
 95                    return new CSVOutput();
 96               break;
 97          }
 98
 99          // daca valoarea primita ca parametru nu este una din constante
100          // se arunca o exceptie
101          throw new Exception('Invalid class type!');
102     }
103
104}

Exemplu:

 1// se de date
 2$data = array(
 3               array(
 4                    'a' => 1,
 5                    'b' => 2,
 6                    'c' => 3
 7                    ),
 8               array(
 9                    'a' => 4,
10                    'b' => 5,
11                    'c' => 6
12                    )
13          );
14
15//Bloc try-catch pentru a prinde eventualele exceptii
16try {
17     // generare obiect
18     $obj = OutputFactory::getInstance(OutputFactory::XML);
19
20     // output headere
21     $obj->header();
22
23     // afisare body
24     echo $obj->body($data);
25
26} catch (Exception $e) {
27
28     $e->getMessage();
29
30}