Factory method design patten in PHP

Citește postarea în română

Share on:

An creational design pattern, which represents an solution for generation objects without specifying the class name. Virtually all methods that generate objects are particular implementations of the Factory Method pattern.

Motivation:

A motivation for this choice is that the creation of the object is delegated to the factory method.

Diagram:

factory method pattern

Implementation:
The classes that generates the objects, the common class to extend and the class with the factory method:

  1// the common class to be extended
  2abstract class OutputBase {
  3     // output the necessary headers
  4     abstract public function header();
  5
  6     // resulting body
  7     abstract public function body($data);
  8
  9}
 10
 11// class for XML ouput
 12class XMLOutput extends OutputBase {
 13
 14     // output XML header
 15     public function header() {
 16          header('content-type: text/xml');
 17     }
 18
 19     // xml document
 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// class for CSV output
 45class CSVOutput extends OutputBase {
 46
 47     // output CSV header
 48     public function header() {
 49          header("Content-type: text/plain");
 50     }
 51
 52     // CSV body
 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// the factory method class
 76// is abstract so it wont be instantiated
 77abstract class OutputFactory {
 78
 79     // constant for XML type
 80     const XML = 1;
 81
 82     // constant for CSV type
 83     const CSV = 2;
 84
 85     // static factory method
 86     public static function getInstance($type) {
 87          // depending which constant was received as a parameter
 88          // one of the objects will be returned
 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          // if the value received as a parameter is not one of the constants
100          // an exception will be thrown
101          throw new Exception('Invalid class type!');
102     }
103
104}

Example:

 1// the data
 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// try-catch block in case of an exception
16try {
17     // generation the object
18     $obj = OutputFactory::getInstance(OutputFactory::XML);
19
20     // output headers
21     $obj->header();
22
23     // display body
24     echo $obj->body($data);
25
26} catch (Exception $e) {
27
28     $e->getMessage();
29
30}