php设计模式

设计模式 一书介绍了很多此类概念。当时,我还在学习面向对象 (OO),因此我发现那本书中有许多概念都很难领会。但是,随着越来越熟悉 OO 概念 —— 尤其是接口和继承的使用 —— 我开始看到设计模式中的实际价值。作为一名应用程序开发人员,即使从不了解任何模式或者如何及何时使用这些模式,对您的职业生涯也没有什么大的影响。但是,我发现了解这些模式以及 developerWorks 文章 “五种常见 PHP 设计模式” 中介绍的那些模式的优秀知识后(请参阅 参考资料),您可以完成两件事情:

启用高带宽会话
如果了解设计模式,您将能够更快地构建可靠的 OO 应用程序。但当整个开发团队知道各种模式时,您可以突然拥有非常高的带宽会话。您不再需要讨论将到处使用的所有类。相反,您可以与其他人谈论模式。“我要在这里引用一个单例(singleton),然后使用迭代器遍历对象集合,然后……” 比遍历构成这些模式的类、方法和接口快很多。单是通信效率一项就值得花时间以团队的形式通过会话来研究模式。
减少痛苦的教训
每个设计模式都描述了一种经过验证的解决常见问题的方法。因此,您无需担心设计是不是正确的,只要您已经选择了提供所需优点的模式。
缺陷
有句谚语说得好:“当您手中拿着一把锤子时,所有事物看上去都像钉子”。当您认为自己找到一个优秀模式时,您可能会尝试到处使用它,即使在不应当使用它的位置。记住您必须考虑正在学习的模式的使用目的,不要为了使用模式而把这些模式强行应用到应用程序的各个部分中。

本文将介绍可用于改进 PHP 代码的五个模式。每个模式都将介绍一个特定场景。可以在 下载 部分中获得这些模式的 PHP 代码。

要求
要发挥本文的最大功效并使用示例,需要在计算机中安装以下软件:

PHP V5 或更高版本(本文是使用 PHP V5.2.4 撰写的)
压缩程序,例如 WinZIP(用于压缩可下载的代码归档)
注:虽然您也可以使用纯文本编辑器,但是我发现拥有语法高亮显示和语法纠错功能的编辑器真的很有帮助。本文中的示例是使用 Eclipse PHP Development Tools (PDT) 编写的。

——摘自《另外五个PHP设计模式》

  • 命令链模式
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
<?php

/**
* 艾瑞可erik
* https://erik.xyz
* 命令链模式
* Interface ICommand
*/
interface ICommand
{
function onCommand($name, $args);
}

class CommandChain
{
private $_command = [];

public static function load()
{
return new CommandChain();
}

public function addCommand($cmd)
{
$this->_command[] = $cmd;
}

public function runCommand($name, $args)
{
foreach ($this->_command as $cmd) {
if ($cmd->onCommand($name, $args)) {
return;
}
}
}
}

class UserCommand implements ICommand
{
public static function load()
{
return new UserCommand();
}

public function OnCommand($name, $args)
{
if ($name != 'addUser') return false;
echo("UserCommand handling 'addUser'\n");
return true;
}
}

class MailCommand implements ICommand
{
public static function load()
{
return new MailCommand();
}

public function onCommand($name, $args)
{
if ($name != 'mail') return false;
echo("MailCommand handling 'mail'\n");
return true;
}
}

$cc = CommandChain::load();
$cc->addCommand(UserCommand::load());
$cc->addCommand(MailCommand::load());
$cc->runCommand('addUser', null);
$cc->runCommand('mail', null);
  • 委托模式
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
76
77
78
79
80
81
<?php

/**
* 艾瑞可erik
* https://erik.xyz
* Class bank
* 委托模式
*/
class bank
{
protected $info = [];

public static function load()
{
return new bank();
}

/**
* 传入参数,设置基本信息
* @param $type
* @param $money
* 设置银行存款类型
*/
public function updateBankInfo($type, $money)
{
$this->info[$type] = $money;
}

public function bankWithdraw($bankType)
{
$obj = $bankType::load();
return $obj->bankMain($this->info);
}
}

/**
* 存款操作
* Class bankDeposit
*/
class bankDeposit
{
public static function load()
{
return new bankDeposit();
}

public function bankMain($data)
{
return $data['bankDeposit'];
}
}

/**
* 取款操作
* Class bankWithdraw
*/
class bankWithdraw
{
public static function load()
{
return new bankWithdraw();
}

public function bankMain($data)
{
return $data['bankWithdraw'];
}
}

$bank = bank::load();

//设置数据
$bank->updateBankInfo("bankWithdraw", 500);
$bank->updateBankInfo("bankDeposit", 100);

//存款
$bankReturn = $bank->bankWithdraw("bankDeposit");
echo "存款" . $bankReturn . PHP_EOL;
//取款
$bankReturn = $bank->bankWithdraw("bankWithdraw");
echo "取款" . $bankReturn . PHP_EOL;
  • 工厂模式(1)
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
<?php
/**
* 艾瑞可erik
* https://erik.xyz
* 工厂模式
*/

/**
* 支付接口
*/
interface PayErik{
public function payMethodErik();
}

class AlipayErik implements PayErik{

public function payMethodErik(){
echo '支付宝支付';
}

}

class WxpayErik implements PayErik
{

public function payMethodErik(){
echo '微信支付';
}

}

/**
* 支付工厂类
*/
class PayFactoryErik{
public static function factoryErik($class_name){
return new $class_name();
}
}

$obj=PayFactoryErik::factoryErik('alipayErik');
$pay=$obj->PayMethodErik();
echo PHP_EOL;
print_r($pay);
echo PHP_EOL;
  • 工厂模式(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
<?php
/**
* 艾瑞可erik
* https://erik.xyz
* 工厂模式
*/

/**
* 支付接口
*/
interface PayErik{
public function payMethodErik();
}

class AlipayErik implements PayErik{

public function load(){
return new alipayErik();
}
public function payMethodErik(){
echo '支付宝支付';
}

}

class WxpayErik implements PayErik
{
public function load(){
return new wxpayErik();
}
public function payMethodErik(){
echo '微信支付';
}

}


$alipayErik=AlipayErik::load();
$payErik=$alipayErik->payMethodErik();
echo PHP_EOL;
print_r($payErik);
unset($alipayErik);
echo PHP_EOL;

$wxpayErik=WxpayErik::load();
$payEriks=$wxpayErik->payMethodErik();
echo PHP_EOL;
print_r($payEriks);
unset($payEriks);
echo PHP_EOL;
  • 观察者模式
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
<?php
/**
*艾瑞可erik
*https://erik.xyz
* 观察者模式
* Interface PayLoggerErik
*/
//支付日志
interface PayLoggerErik
{
public function onChangeErik($sender, $args);
}

//支付选择
interface PayTypeErik
{
public function addObserverErik($observer);
}

class PayListErik implements PayTypeErik
{
private $observers = [];

public function load()
{
return new PayListErik();
}

public function addCustomerErik($method, $name)
{
if (empty($method)) {
return false;
}
foreach ($this->observers as $obs) {
$obs->$method($this, $name);
}
}

public function addObserverErik($observer)
{
$this->observers[] = $observer;
}
}

/** 日志记录
* Class PayListLoggerErik
*/
class PayListLoggerErik implements PayLoggerErik
{
public function load()
{
return new PayListLoggerErik();
}

public function onChangeErik($sender, $args)
{
echo "选择成功!" . $args . PHP_EOL;
}

public function setLoggerErik($sender, $args)
{
echo "设置成功了!" . $args. PHP_EOL;
}
}

$payList = PayListErik::load();
$payList->addObserverErik(PayListLoggerErik::load());
$payList->addCustomerErik('onChangeErik', "艾瑞可erik(https://erik.xyz),新增日志记录引入");
$data = $payList->addCustomerErik('setLoggerErik', "艾瑞可erik(https://erik.xyz)");
  • 单例模式
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
<?php
/**
* 艾瑞可erik
* https://erik.xyz
*
* 单例模式
*/
class SingleErik
{
private $props=[];
private static $instanceErik;
final private function __construct(){}

//单例方法
public static function getInstanceErik(){
if(empty(self::$instanceErik)){
self::$instanceErik=new SingleErik();
}
return self::$instanceErik;
}

//单例定义方法
public function setPropertyErik($key,$val){
$this->props[$key]=$val;
}

public function getPropertyErik($key){
return $this->props[$key];
}

final protected function __clone(){}
}

$perf=singleErik::getInstanceErik();
$perf->setPropertyErik("blog",["title"=>"艾瑞可erik","url"=>"https://erik.xyz"]);
$getData=$perf->getPropertyErik("blog");
print_r($getData);
//销毁引用,释放空间
unset($perf);
  • 策略模式
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?php
/**
* 艾瑞可erik
* https://erik.xyz
* Interface IStrategy
* 策略模式
*/

interface IStrategyErik
{
function filter($record);
}

class FindAfterStrategyErik implements IStrategyErik
{
private $_name;

public function __construct($name)
{
$this->_name = $name;
}

public static function load($name)
{
return new FindAfterStrategyErik($name);
}

public function filter($record)
{
return strcmp($this->_name, $record) <= 0;
}
}

class RandomStrategyErik implements IStrategyErik
{
public static function load()
{
return new RandomStrategyErik();
}

public function filter($record)
{
return rand(0, 1) >= 0.5;
}
}

class UserListErik
{
private $_list = [];

public static function load($arr = [])
{
return new UserListErik($arr);
}

public function __construct($names)
{
if ($names != null) {
foreach ($names as $name) {
$this->_list[] = $name;
}
}
}

public function add($name)
{
$this->_list[] = $name;
}

public function find($filter)
{

$recs = [];
foreach ($this->_list as $user) {
if ($filter->filter($user)) {
$recs[] = $user;
}
}

return $recs;
}
}

$ul = UserListErik::load(["Andy", "Jack", "Lori", "Megan"]);
$f1 = $ul->find(FindAfterStrategyErik::load("J"));
print_r($f1);

$f2 = $ul->find(RandomStrategyErik::load());
print_r($f2);

参考资料:

另外五个 PHP 设计模式

PHPer进阶