Factory method design patten in PHP
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:
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}