Skip to content

PHP:设计模式之工厂模式(Factory Pattern)

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式在《Java与模式》中分为三类:
1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

工厂方法模式
The main goal of this pattern is delivering an object by hiding all the complexities behind it.
假设我们现在要开发一个Blog系统,为了方便用户在部署这个系统的时候,可以选用不同的数据库系统支持,如MySQL,PostgreSQL,Oracle,MSSQL等。因此我们在系统中创建数据库连接及操作的时候,适合各个数据库系统。
MySQL数据库Manager类

class MySQLManager{
  public function setHost($host)  {
      //set db host
  }
  public function setDB($db)  {
    //set db name
  }
  public function setUserName($user)  {
    //set user name
  }
  public function setPassword($pwd)  {
    //set password
  }
  public function connect()  {
    //now connect
  }
}

PostgreSQL数据库系统Manager类

class PostgreSQLManager{
  public function setHost($host)  {
    //set db host
  }
  public function setDB($db)  {
    //set db name
  }
  public function setUserName($user)  {
    //set user name
  }
  public function setPassword($pwd)  {
    //set password
  }
  public function connect()  {
    //now connect
  }
}

正常的情况下,我们可以创建如下的代码:

  if ($dbtype == "mysql")
  //use mysql class
  else if ($dbtype == "postgresql")
  //use postgresql class

但是一个问题就出来了,如果现在有很多的数据库系统,增加了Oracle,MSSQL等等更多的数据库系统的支持呢,这样我们就得不得不做很多if else的选择。
现在的解决方案可以用一个工厂类,把所有数据库系统类放在这个类来处理。
工厂类:

class DBManager{
  public static function setDriver($driver) {
    $this->driver = $driver;
  //set the driver
  }
  public static function connect() {
    if ($this->driver == "mysql")    {
      $MM = new MySQLManager();
      $MM->setHost("host");
      $MM->setDB("db");
      $MM->setUserName("user");
      $MM->setPassword("pwd");
      $this->connection = $MM->connect();
    } else if($this->driver=="pgsql") {
      $PM = new PostgreSQLManager();
      $PM->setHost("host");
      $PM->setDB("db");
      $PM->setUserName("user");
      $PM->setPassword("pwd");
      $this->connection= $PM->connect();
    }
  }
}

然后就可以用工厂类DBManager来实例化

$DM = new DBManager();
$DM->setDriver("mysql");
$DM->connect("host","user","db","pwd");

这样DBManager工厂类就封装了里面复杂的数据库实例化的逻辑。

抽象工厂模式
抽象工厂模式(Abstact Factory)是一种常见的软件设计模式。该模式为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类。

假设我们有两种产品接口 Button 和 Border ,每一种产品都支持多种系列,比如 Mac 系列和 Windows 系列。这样每个系列的产品分别是 MacButton, WinButton, MacBorder, WinBorder 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族建立一个工厂 MacFactory 和 WinFactory 。每个工厂都有两个方法 CreateButton 和 CreateBorder 并返回对应的产品,可以将这两个方法抽象成一个接口 AbstractFactory 。这样在运行时刻我们可以选择创建需要的产品系列。
PHP示例代码

<?php
/***************************************************************************
 *              AbstractFactory.php
 *
 ***************************************************************************/
abstract class AbstractFactory {
	abstract public function CreateButton();
	abstract public function CreateBorder();
}

class MacFactory extends AbstractFactory{
	public function CreateButton(){
		return new MacButton();
	}
	public function CreateBorder(){
		return new MacBorder();
	}
}
class WinFactory extends AbstractFactory{
	public function CreateButton(){
		return new WinButton();
	}
	public function CreateBorder(){
		return new WinBorder();
	}
}
class AbstractButton{}
class AbstractBorder{}

class MacButton extends AbstractButton{
	function __construct()	{
		echo 'MacButton is created' . "\n";
	}
}
class MacBorder extends AbstractBorder{
	function __construct()	{
		echo 'MacBorder is created' . "\n";
	}
}

class WinButton extends AbstractButton{
	function __construct()	{
		echo 'WinButton is created' . "\n";
	}
}
class WinBorder extends AbstractBorder{
	function __construct()	{
		echo 'WinBorder is created' . "\n";
	}
}
?>
那么客户可以根据需要选择 Mac 风格或者 Win 风格的 Button 或 Border 来创建
$type = 'Mac'; //value by user.
if(!in_array($type, array('Win','Mac'))
    die('Type Error');
$factoryClass = $type.'Factory';
$factory=new $factoryClass;
$factory->CreateButton();
$factory->CreateBorder();



Related posts

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*
备案/许可证编号为: 浙ICP备09097601号 | 网址专家互链 | 友情链接站