PHP工厂模式就是用一个工厂方法来替换掉直接new对象的操作。
在传统习惯中,如果要生成一个类的话,在代码中直接new一个对象,比如:
<?php class Database { } $db = new Database();
下面介绍工厂模式的操作方法:
<?php class Database { } class Factory{ static function createDatabase(){ $db = new Database(); return $db; } }
那么,当我们想创建一个数据库类的话,就可以使用这样的方法:
$db = Factory::createDatabase();
简单工厂模式比直接new一个对象的好处是,比如Database这个类在很多php文件中都有使用到,当Database这个类发生了某些变更,比如修改了类名、或者一些参数发生了变化,那这时候如果你使用的是$db = new Database这种传统方法生成对象,那么在所有包含这种生成对象的php文件代码中都要进行修改。而使用工厂模式,只要在工厂方法或类里面进行修改即可。而且工厂模式是其他设计模式的基础。
对上面的简单工厂模式再进一步优化,比如:
<?php class Database { static function Factory($type){ if(include_once 'Drivers/'.$type.'.php'){ $classname = 'Drivers_'.$type; return new $classname; }else{ throw new Exception('Driver not found'); } } } $mysql = Database::Factory('MySQL'); $sqlite = Database::Factory('SQLite');
简单工厂模式又称静态工厂方法模式。从命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。
要理解工厂模式这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完全不相关的部分中也有可能出现级联破坏。
该问题在于紧密耦合 。系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。您需要一组模式,使这些类能够相互通信,但不希望将它们紧密绑定在一起,以避免出现联锁。
在大型系统中,许多代码依赖于少数几个关键类。需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
<?php interface IUser{ function getName(); } class User implements IUser{ public $id; public function __construct($id){ } public function getName() { return "Jack"; } }
传统方法使用 User 类,一般都是这样:
$obj1 = new User(1); $obj2 = new User(2); $obj3 = new User(3);
这时候,由于新的需求,使得User类要新增个参数或者User类名称发生变化,User 类代码发生变动(因为某个奇葩需要改动类名,虽然可能概率很小,这里只是为了举例。),即:
<?php interface IUser{ function getName(); } class UserObj implements IUser{ public $id; public $pre; public function __construct($id){ } public function getName() { return "Jack"; } }
接着,恐怖的事情发生了,假设之前有 100 个页面引用了之前的 User 类,那么这 100 个页面都要发生相应的改动
$obj1 = new UserObj(1); $obj2 = new UserObj(2); $obj3 = new UserObj(3); $obj4 = new UserObj(4); $obj5 = new UserObj(5);
本来是一个小小的改动,但因紧密耦合的原因使得改动大吐血。而使用工厂模式则可以避免发生这种情况:
<?php interface IUser{ function getName(); } class UserObj implements IUser{ public $id; public $pre; public function __construct($id){ } public function getName() { return "Jack"; } } class UserFactory{ static public function create($id){ return new UserObj($id); } } UserFactory::create(1); UserFactory::create(2);