设计模式-工厂模式
工厂模式就是一种类,是指包含一个专门用来创建其他对象的方法的类,工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活。
工厂模式通常用来返回符合类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者,从而允许我们基于应用程序逻辑或者配置设置来决定应实例化哪一个类,例如,可以使用这样的提供者来扩展一个类,而不需要重构应用程序的其他部分,从而使用新的扩展后的名称 。
通常,工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,工厂方法可以任意命名,这个静态还可以接受任意数据的参数,必须返回一个对象。
具有为您创建对象的某些方法,这样就可以使用工厂类创建对象,工厂模式在于可以根据输入参数或者应用程序配置的不同来创建一种专门用来实现化并返回其它类的实例的类,而不直接使用new,这样如果想更改创建的对象类型,只需更改该工厂即可。
class Factory { // 创建一个基本的工厂类 static public function fac($id){ // 创建一个返回对象实例的静态方法 if(1 == $id) return new A(); elseif(2==$id) return new B(); elseif(3==$id) return new C(); return new D(); } } interface FetchName {//创建一个接口 public function getname();// } class A implements FetchName{ private $name = "AAAAA"; public function getname(){ return $this->name; } } class C implements FetchName{ private $name = "CCCCC"; public function getname(){ return $this->name; } } class B implements FetchName{ private $name = "BBBBB"; public function getname(){ return $this->name; } } class D implements FetchName{ private $name = "DDDDD"; public function getname(){ return $this->name; } } $o = Factory::fac(6);//调用工厂类中的方法 if($o instanceof FetchName){ echo $o->getname();//DDDDD } $p = Factory::fac(3); echo $p->getname();//CCCCC
PHP工厂模式就是用一个工厂方法来替换掉直接new对象的操作,就是为方便扩展,方便使用。在新增实现基类中的类中方法时候,那么在工厂类中无需修改,传入参数可以直接使用,具体就是跳过工厂类修改,直接使用工厂类输出想要的结果。在传统习惯中,如果要生成一个类的话,在代码中直接new一个对象,比如:
class Database{ } $db = new Database();
工厂模式的操作方法:
class Database{ } //创建一个工厂类 class Factory { //创建一个静态方法 static function createDatabase(){ $db = new Database; return $db; } }
当我们想创建一个数据库类的话,就可以使用这样的方法:
$db = Factory::createDatabase();
简单工厂模式比直接 new 一个对象的好处是,比如Database这个类在很多php文件中都有使用到,当Database这个类发生了某些变更,比如修改了类名、或者一些参数发生了改变,那这时候如果你使用的是$db = new Database这种传统方法生成对象,那么在所有包含这种生成对象的php文件代码中都要进行修改。而使用工厂模式,只要在工厂方法或类里面进行修改即可。而且工厂模式是其他设计模式的基础。
对上面的简单工厂模式再进一步优化,比如利用工厂类生产对象:
class Example { // The parameterized factory method public static function factory($type) { if (include_once 'Drivers/' . $type . '.php') { $classname = 'Driver_' . $type; return new $classname; } else { throw new Exception('Driver not found'); } } } // Load a MySQL Driver $mysql = Example::factory('MySQL'); // Load an SQLite Driver $sqlite = Example::factory('SQLite');
简单工厂模式又称静态工厂方法模式,它存在的目的很简单:定义一个用于创建对象的接口。
在大型的系统开发中,在更改一个代码片段时,可能会影响其他部分,原因在于紧密耦合,系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。这里就需要一组模式,使这些类能够相互通信,但不希望将它们紧密绑定在一起,以避免出现联锁。
在大型系统中,许多代码依赖于少数几个关键类,需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
interface IUser { function getName(); } class User implements IUser { public $id; public function __construct( $id ) { } public function getName() { return "Fantasy"; } }
传统方法使用 User 类,一般都是这样:
//在页面1 $obj = new User(1); //在页面2 $obj2 = new User(2); //在页面3 $obj3 = new User(3); ....
这时候,由于新的需求,使得User类要新增个参数或者User类名称发生变化,User 类代码发生变动,即:
class User implements IUser { public $id,$pre; public function __construct( $id , $pre = '') {...} public function getName() { return $this->pre."Fantasy"; } }
接着,恐怖的事情发生了,假设之前有 100 个页面引用了之前的 User 类,那么这 100 个页面都要发生相应的改动:
//在页面1 $obj = new User(1,'aaa'); //在页面2 $obj = new User(2,'aaa'); //在页面3 $obj = new User(3,'aaa'); ...
本来是一个小小的改动,但因紧密耦合的原因使得改动大吐血。而使用工厂模式则可以避免发生这种情况:
//User类为变动前 class UserFactory { public static function Create( $id ) { return new User( $id ); } } //页面1 $uo1 = UserFactory::Create( 1 ); //页面2 $uo12 = UserFactory::Create( 2 ); ....
这时候需求变动,User 类也发生变动:
class User implements IUser { public $id,$pre; public function __construct( $id , $pre = '') {...} public function getName() { return $this->pre."Jack"; } }
但是,我们不再需要去改动这 100 个页面,我们要改的仅仅是这个工厂类:
class UserFactory { public static function Create( $id,$pre = 'aaa' ) { return new User( $id ,$pre); } }
其他100个页面不用做任何改动,这就是工厂设计模式带来的好处。看下UML图: