设计模式: 单态 和 工厂

单态模式
它们必须拥有一个构造函数并且必须被标记为private
它们拥有一个保存类的实例的静态成员变量。
它们拥有一个访问这个实例的公共的静态方法。

作为这一模式的一部分,必须创建一个空的私有的__clone()方法,以防止对象被复制或者克隆。

返回实例引用的这个方法通常被命名为getInstance(),这个方法必须是静态的,而且如果它还没有实例化,就必须进行实例化。getInstance()方法通过使用instanceof操作符和selft关键字,可以检测到类是否已经被初始化,如果保存实例的静态成员为空或者还不是类的自身的一个实例,那么这个实例将会被创建并保存到存放实例的变量中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

class Database{
private $_db;
static $_instance;
private function __construct(){
$this->_db = pg_connect(‘dbname=example_db’);
}
private __clone(){};
public static function getInstance(){
if(!(self::$_instance instanceof self)){
self::$_instance = new self();
}
return self::$_instance;
}
}

工厂模式
工厂类是指包含了一个专门用来创建其它对象的类。
通常,工厂模式有一个关键的构造,即根据一般原则被命名为factory的静态方法。这个静态方法还可以接受任意数量的参数,并且必须返回一个对象。
[工厂使用模子来生产产品,模子就是类,产品就是类的实例,所以工厂类就是实例化其它类的类]
应用:
在使用数据库的应用程序中,工厂模式可以在以下两个方面起作用。
更容易支持各种不同的数据库平台。
如果软件是内部使用软件,那么在需要修改数据库时,可以很容易将应用程序移植到另外一个平台。

比如希望创建一个名为user的数据库表来测试它,这个表应该定义一个名为email的varchar类型的字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

interface IDatabaseBindings{
public function userExists($email);
}

class PGSQL implements IDatabaseBindings{
protected $_connection;

public function __construct(){
$this->_connection = pg_connect('dbname=example_db');
}

public function userExists($email){
$emailEscaped = pg_escape_string($email);
$query ="select 1 from users where email ='".$emailEscaped."'";
if($result = pg_query($query,$this->_connection)){
return (pg_num_rows($result) > 0)?true:false;
}else{
return false;
}
}
}

class MYSQL implements IDatabaseBindings{
protected $_connection;
public function __construct(){}
public function userExists($email){}
}

class DatabaseFactory{
public static function factory(){
$type = loadtypefromconfigfile();
switch($type){
case 'PGSQL':
return new PGSL();
break;
case 'MYSQL':
return new MYSQL();
break;
}
}
}

用法
$db = DatabaseFactory::factory();
$db->userExists(‘person@example.com’);

这个例子创建了两个实现类:一个是为PostgreSQL层实现的PGSQL类,另一个是为MySQL层实现的MySQL类,应用程序的其余部分将完全不知道它与何种类型的数据库打交道,只会基于IDatabaseBindings接口定义的规则直接与工厂返回的实例打交道。

坚持原创技术分享,您的支持将鼓励我继续创作!