PHP设计模式——工厂模式
原文: http://coderschool.cn/1521.html
这一篇也讲得不错!!
http://www.cnblogs.com/wangtao_20/p/3594192.html
http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html
------------------------------------------------------------------------------------------------
PHP工厂模式就是用一个工厂方法来替换掉直接new对象的操作。
在传统习惯中,如果要生成一个类的话,在代码中直接new一个对象,比如:
1
2
3
4
5
|
class Database{ } $db = new Database(); |
下面介绍工厂模式的操作方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Database{ } //创建一个工厂类 class Factory { //创建一个静态方法 static function createDatabase(){ $db = new Database; return $db; } } |
那么,当我们想创建一个数据库类的话,就可以使用这样的方法:
1
|
$db = Factory::createDatabase(); |
简单工厂模式比直接new一个对象的好处是,比如Database这个类在很多php文件中都有使用到,当Database这个类发生了某些变更,比如修改了类名、或者一些参数发生了变化,那这时候如果你使用的是$db = new Database这种传统方法生成对象,那么在所有包含这种生成对象的php文件代码中都要进行修改。而使用工厂模式,只要在工厂方法或类里面进行修改即可。而且工厂模式是其他设计模式的基础。
对上面的简单工厂模式再进一步优化,比如:
利用工厂类生产对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?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 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
看下实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?php interface IUser { function getName(); } class User implements IUser { public $id; public function __construct( $id ) { } public function getName() { return "Jack"; } } |
传统方法使用 User 类,一般都是这样:
1
2
3
4
5
6
7
8
9
|
//在页面1 $obj = new User(1); //在页面2 $obj2 = new User(2); //在页面3 $obj3 = new User(3); .... |
这时候,由于新的需求,使得User类要新增个参数或者User类名称发生变化,User 类代码发生变动,即:
1
2
3
4
5
6
7
8
9
10
|
class User implements IUser { public $id,$pre; public function __construct( $id , $pre = '') {...} public function getName() { return $this->pre."Jack"; } } |
接着,恐怖的事情发生了,假设之前有 100 个页面引用了之前的 User 类,那么这 100 个页面都要发生相应的改动:
1
2
3
4
5
6
7
8
9
|
//在页面1 $obj = new User(1,'aaa'); //在页面2 $obj = new User(2,'aaa'); //在页面3 $obj = new User(3,'aaa'); ... |
本来是一个小小的改动,但因紧密耦合的原因使得改动大吐血。而使用工厂模式则可以避免发生这种情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//User类为变动前 class UserFactory { public static function Create( $id ) { return new User( $id ); } } //页面1 $uo1 = UserFactory::Create( 1 ); //页面2 $uo12 = UserFactory::Create( 2 ); .... |
这时候需求变动,User 类也发生变动:
1
2
3
4
5
6
7
8
9
10
|
class User implements IUser { public $id,$pre; public function __construct( $id , $pre = '') {...} public function getName() { return $this->pre."Jack"; } } |
但是,我们不再需要去改动这 100 个页面,我们要改的仅仅是这个工厂类:
1
2
3
4
5
6
7
8
|
// class UserFactory { public static function Create( $id,$pre = 'aaa' ) { return new User( $id ,$pre); } } |
其他100个页面不用做任何改动,这就是工厂设计模式带来的好处。看下UML图: