0%

PHP常见六大设计模式及举例

设计模式在php开发中用途还是非常多,能够使用设计模式并准确选择设计模式将事半功倍的提高开发效率,而且也能提高代码可读性和提升代码解耦度,非常方便以后我们在迭代功能的时候的扩展与重构,不至于看到自己以前写的代码无所适从。

1、单例模式

单例模式:即一个类只被实例化一次,当其他人对其再次实例化时,返回第一次实例化的对象,可以避免大量的new
操作,减少资源的消耗,典型应用于数据库类的实例化。
特点:三私一公 (私有静态属性instance,私有构造方法,私有克隆方法,公有化静态方法getInstance)

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
<?php 

class Singleton
{
//私有静态属性
private static $instance;
//私有构造方法,禁止使用new创建对象
private function __construct(){}
//该实例的出口
public static function getInstance(){
if (!isset(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
//将克隆方法设为私有,禁止克隆对象
private function __clone(){}

public function say()
{
echo "这是用单例模式创建对象实例 <br>";
}
public function operation()
{
echo "这里可以添加其他方法和操作 <br>";
}
}

// $shiyanlou = new Singleton();
$shiyanlou = Singleton::getInstance();
$shiyanlou->say();
$shiyanlou->operation();

$newShiyanlou = Singleton::getInstance();
var_dump($shiyanlou === $newShiyanlou);

2、工厂模式

工厂模式解决的是如何不通过new建立实例对象的方法。

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php 

// 电视接口
interface TV {
public function open();
public function close();
}

// 实现类
class XiaomiTv implements TV
{

public function open()
{
echo "open 小米 TV <br>";
}

public function close()
{
echo "close 小米 TV <br>";
}

}

// 电脑接口
interface PC {
public function work();
public function paly();
}

class LenovoPc implements PC
{

public function work()
{
echo "I‘m working on lenovo computer <br>";
}

public function paly()
{
echo "Lenovo computer can be use to paly games <br>";
}
}

// 工厂抽象类
abstract class Factory {
abstract public static function createPc();
abstract public static function createTv();
}

class ProductFactory extends Factory {
public static function createTv
{
return new HaierTv();
}

public static function createPc()
{
return new LenovoPc();
}
}



$newTv = ProductFactory::createTv();
$newTv->open();
$newTv->close();

$newPc = ProductFactory::createPc();
$newPc->work();
$newPc->paly();

3、策略模式

针对一组算法,将每一个算法封装到具有共同接口的独立的类中,例如进入个人主页时,根据浏览者的不同,给予不同的显示与操作

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
<?php 

/*
* 声明策略文件的接口,约定策略包含的行为。
*/
interface UserStrategy
{
function showAd();
function showCategory();
}

class FemaleUser implements UserStrategy
{
function showAd(){
echo "2016冬季女装";
}
function showCategory(){
echo "女装";
}
}

class MaleUser implements UserStrategy
{
function showAd(){
echo "IPhone6s";
}
function showCategory(){
echo "电子产品";
}
}

4、适配器模式

将各种截然不同的函数接口封装成统一的API。
PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。
类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。
首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

1
2
3
4
5
6
interface IDatabase
{
function connect($host, $user, $passwd, $dbname);
function query($sql);
function close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#MYSQL
class MySQL implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname, $conn);
$this->conn = $conn;
}

function query($sql)
{
$res = mysql_query($sql, $this->conn);
return $res;
}

function close()
{
mysql_close($this->conn);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#MySQLi
class MySQLi implements IDatabase
{
protected $conn;

function connect($host, $user, $passwd, $dbname)
{
$conn = mysqli_connect($host, $user, $passwd, $dbname);
$this->conn = $conn;
}

function query($sql)
{
return mysqli_query($this->conn, $sql);
}

function close()
{
mysqli_close($this->conn);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#PDO
class PDO implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd);
$this->conn = $conn;
}
function query($sql)
{
return $this->conn->query($sql);
}

function close()
{
unset($this->conn);
}
}

5、注册模式

注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 

class Register
{
protected static $objects;
function set($alias,$object)//将对象注册到全局的树上
{
self::$objects[$alias]=$object;//将对象放到树上
}
static function get($name){
return self::$objects[$name];//获取某个注册到树上的对象
}
function _unset($alias)
{
unset(self::$objects[$alias]);//移除某个注册到树上的对象。
}
}

6、观察者模式

1:观察者模式(Observer),当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。
2:场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php 

interface Observer
{
public function update($obj);
}

class Message implements Observer
{
//....

function update($obj)
{
echo '发送新订单短信(' . $obj->mobile . ')通知给商家!';
}

//....
}

class Goods implements Observer
{
//....

public function update($obj)
{
echo '修改商品' . $obj->goodsId . '的库存!';
}

//....
}

class Order
{
private $observers = [];
public function attach($ob)
{
$this->observers[] = $ob;
}

public function detach($ob)
{
$position = 0;
foreach ($this->observers as $ob) {
if ($ob == $observer) {
array_splice($this->observers, ($position), 1);
}
++$position;
}
}
public function notify($obj)
{
foreach ($this->observers as $ob) {
$ob->update($obj);
}
}
public function sale()
{
// 商品卖掉了
// ....
$obj = new stdClass();
$obj->mobile = '13888888888';
$obj->goodsId = 'Order11111111';
$this->notify($obj);
}
}

$message = new Message();
$goods = new Goods();
$order = new Order();
$order->attach($message);
$order->attach($goods);

// 订单卖出了!!
$order->sale();