工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式在《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();
Post a Comment