PHP中使用工厂模式

网络整理 - 08-26

  工厂类是指包含一个专门用来创建其他对象的方法的类,工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活,熟练掌握工厂模式高级PHP开发人员是很重要的。

  工厂模式通常用来返回符合类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者,从而允许我们基于应用程序逻辑或者配置设置来决定应实例化哪一个类,例如,可以使用这样的提供者来扩展一个类,而不需要重构应用程序的其他部分,从而使用新的扩展后的名称 。

  通常,工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,工厂方法可以任意命名,这个静态还可以接受任意数据的参数,必须返回一个对象。

  基本的工厂类

  01class MyObject{

  02 //对象将从工厂返回

  03}

  04

  05class MyFactory{

  06public static function factory(){

  07return new MyObject():

  08 }

  09}

  10

  11

  12$instance=MyFactory::factory();

  13

  14

  15使用工厂类解析图像文件

  1

  01<?php

  02interface IImage{

  03 function getHeight();

  04 function getWidth();

  05 function getData();

  06}

  07

  08class Image_PNG implements IImage{

  09

  10 private $_width,$_height,$_data;

  11

  12 public function __construct($file){

  13 $this->_file=$file;

  14 $this->_parse();

  15 }

  16

  17 private function _parse(){

  18

  19 //完成PNG格式的解析工作

  20 //并填充$_width,$_height,$_data;

  21 }

  22

  23

  24 public function getWidth(){

  25 return $this->_width;

  26 }

  27 public function getHeight(){

  28 return $this->_height;

  29 }

  30

  31 public function getData(){

  32 return $this->_data;

  33

  34 }

  35

  36}

  37

  38class Image_JPEG implements IImage{

  39

  40 private $_width,$_height,$_data;

  41

  42 public function __construct($file){

  43 $this->_file=$file;

  44 $this->_parse();

  45 }

  46

  47 private function _parse(){

  48

  49 //完成JPEG格式的解析工作

  50 //并填充$_width,$_height,$_data;

  51 }

  52

  53

  54 public function getWidth(){

  55 return $this->_width;

  56 }

  57 public function getHeight(){

  58 return $this->_height;

  59 }

  60

  61 public function getData(){

  62 return $this->_data;

  63

  64 }

  65

  66}

  67

  68class ImageFactory{

  69

  70 public static function factory($file){

  71 $pathParts=pathinfo($file);

  72 switch (strtolower($pathParts['extension']))

  73 {

  74 case 'jpg':

  75 $ret=new Image_JPEG($file);

  76 break;

  77 case 'png':

  78 $ret=new Image_PNG($file);

  79 break;

  80 default:

  81 //有问题

  82

  83

  84 }

  85 if($ret instanceof IImage){

  86 return $ret;

  87 }else {

  88 //有问题

  89 }

  90 }

  91}

  92

  93//当使用图像文件名调用 工厂方法时,根据传入的文件类型不同,取得不同对象。

  1//调用ImageFactoyr

  2$image=ImageFactory::factory('/path/to/my.jpg');

  3//$image是Image_JPEG类的一个实例

  4echo $image->getWidth();

  使用工厂类解决数据库可移值性问题

  在数据库应用程序中,工厂模式可以在以下两个方面起作用。

  1.使软件更容易支持各种不同的数据库平台,用于扩展用户群

  2.如果软件是内部使用,需要修改数据库时,可以容易将应用程序移值到别一个平台

  在代码中,创建了一个名为User的数据库表来测试它,这个表定义一个名为email的varchar类型字段

  01<?php

  02interface IDatabaseBindings{

  03 public function userExists($email);

  04}

  05

  06class PGSQL implements IDatabaseBindings{

  07 protected $_connection;

  08

  09 public function __construct(){

  10

  11 $this->_connection=pg_connect('dbname=example_db');

  12 }

  13

  14 public function userExists($email){

  15

  16 $emailEscaped=pg_escape_string($email);

  17 $query="select 1 from users where email='".$emailEscaped."'";

  18 if($result=pg_query($query,$this->_connection)){

  19 return (pg_num_rows($result)>0)?true:false;

  20 }else{

  21 return false;

  22 }

  23 }

  24

  25}

  26

  27class MYSQL implements IDatabaseBindings{

  28

  29 protected $_connection;

  30

  31 public function __construct(){

  32

  33 $this->_connection=mysql_connect('localhost');

  34 mysql_select_db('example_db',$this->_connection);

  35 }

  36

  37 public function userExists($email){

  38

  39 $emailEscaped=mysql_real_escape_string($email);

  40 $query="select 1 from users where email='".$emailEscaped."'";

  41 if($result=mysql_query($query,$this->_connection)){

  42 return (mysql_num_rows($result)>0)?true:false;

  43 }else{

  44 return false;

  45 }

  46 }

  47

  48}

  49

  50class DatabaseFactory{

  51

  52 public static function factory(){

  53 $type=loadtypefromconfigfile();

  54 switch ($type){

  55 case 'PGSQL':

  56 return new PGSQL();

  57 break;

  58 case 'MYSQL':

  59 return new MYSQL();

  60 break;

  61 }

  62 }

  63

  64

  65}

  应用程序不必知道它与何种类型的数据库连接,只会基于IDatabaseBindings接口定义的规则直接与工厂返回的实例打交道。

  //调用DatabaseFactoy

  $db=DatabaseFactory::factory();

  $db->userExists('person@example.com');