php设计模式

设计模式是一个长期思考的问题,随着工作的使用,每一次看都会有新的理解。
感觉工厂类策略模式用的多一些,观察者很少用。其他的几乎用户到。

1.单例模式

为什么使用单例模式

  1. php的应用主要在于数据库应用, 一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时, 如果使用单例模式, 则可以避免大量的new 操作消耗的资源,还可以减少数据库连接这样就不容易出现 too many connections情况。
  2. 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分。
  3. 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中,
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
class man
{
//保存例实例在此属性中
private static $_instance; //也可以设置为null,通过 x === null进行判断

//构造函数声明为private,防止直接创建对象
private function __construct()
{
echo '我被实例化了!';
}

//单例方法
public static function get_instance()
{
//判断一下是否已经被实例过了
if(!isset(self::$_instance))
{
self::$_instance=new self();
}
return self::$_instance;
}

//私有化 阻止用户复制对象实例
final protected function __clone()
{
trigger_error('Clone is not allow' ,E_USER_ERROR);
}
}

// 这个写法会出错,因为构造方法被声明为private
$test = new man;

// 下面将得到Example类的单例对象
$test = man::get_instance();
$test = man::get_instance();

// 复制对象将导致一个E_USER_ERROR.
$test_clone = clone $test;

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
/**
* 定义个抽象的类,让子类去继承实现它
*/
abstract class Operation{
//抽象方法不能包含函数体
abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
}

/**
* 加法类
*/
class OperationAdd extends Operation {
public function getValue($num1,$num2){
return $num1+$num2;
}
}
/**
* 减法类
*/
class OperationSub extends Operation {
public function getValue($num1,$num2){
return $num1-$num2;
}
}

我们可以很方便的扩展程序,添加自己需要的东西,下面我们添加一个乘法的类

1
2
3
4
5
6
7
8
/**
* 乘法类
*/
class OperationMul extends Operation {
public function getValue($num1,$num2){
return $num1*$num2;
}
}

下面就是工厂类的实现了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 工程类,主要用来创建对象
* 功能:根据输入的运算符号,工厂就能实例化出合适的对象
*/
class Factory{
public static function createObj($operate){
switch ($operate){
case '+':
return new OperationAdd();
break;
case '-':
return new OperationSub();
break;
case '*':
return new OperationSub();
break;
}
}
}
$test=Factory::createObj('*');
$result=$test->getValue(23,0);
echo $result;

工厂模式的描述

以交通工具为例子:要求请既可以定制交通工具,又可以定制交通工具生产的过程
定制交通工具
1.定义一个接口,里面包含交工工具的方法(启动 运行 停止)
2.让飞机,汽车等类去实现他们
定制工厂(通上类似)
1.定义一个接口,里面包含交工工具的制造方法(启动 运行 停止)
2.分别写制造飞机,汽车的工厂类去继承实现这个接口

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

abstract class option{
//抽象方法不能包含函数体
abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
}

interface Factory
{
function createOption(); //创造操作
}
//添加相加类
class AddOption impletents option
{
punlic function getValue($a,$b)
{
return $a + $b;
}
}
//添加加法工厂
class addFactory impletents Factory
{
return new getValue();
}

$add = new addFactory();
$add->getValue('1','2');

使用了工厂类就可以不修改其他扩展地方代码的情况下,就行自由的扩展了。

1
2
3
4
5
6
7
8
9
10
11
12
13
//添加相加类
class SubOption impletents option
{
punlic function getValue($a,$b)
{
return $a - $b;
}
}
//添加加法工厂
class subFactory impletents Factory
{
return new SubOption();
}

4.观察者模式

下面是观察者模式的js实现,观察者模式可以很方便的进行更多内容的扩展,我们在添加一些更多的扩展。

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>oop观察者模式</title>
</head>
<body>
<select>
<option value="1">风格1</option>
<option value="2">风格2</option>
</select>
<div id="content" style="margin-top:10px; width: 200px; height: 200px; background: red; text-align: center; line-height: 200px;">
风格1内容
</div>
<div id="ad" style="width: 200px; margin-top: 10px; text-align: center; line-height: 30px; height: 30px; border: 1px solid #ccc;">
ad_1
</div>
<script type="text/javascript">
var sel = document.getElementsByTagName('select')[0];
sel.observers = {};
sel.attach = function (key,obj) {
sel.observers[key] = obj;
}
sel.detach = function (key) {
delete sel.observers[key];
}
sel.onchange = sel.notify = function () {
for(var key in this.observers){
this.observers[key].update(this);
}
}
//客户端
var content = document.getElementById('content');
var ad = document.getElementById('ad');
//content风格切换
content.update = function (observe) {
if(observe.value == '1')
{
this.style.backgroundColor = 'red';
this.innerHTML = '风格1';
}
else
{
this.style.backgroundColor = 'green';
this.innerHTML = '风格2';
}
}
//ad风格切换
ad.update = function (observe) {
if(observe.value == '1')
{
this.innerHTML = 'ad_1';
}
else
{
this.innerHTML = 'ad_2';
}
}

//让content观察select的变化
sel.attach('content',content);
sel.attach('ad',ad);
</script>
</body>
</html>

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
//具体观察对象,发生变化的地方
class spl implements SplSubject
{
public $val = '';
protected $observers = null;

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

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

public function detach(SplObserver $observer)
{
if($idx = array_search($observer, $this->observers, true))
{
unset($this->observers[$idx]);
}
}
//通知观察者
public function notify()
{
foreach ($this->observers as $observer)
{
echo '开始通知观察者<br/>';
$observer->update($this);
}
return TRUE;
}

public function setValue($value)
{
$this->val = $value; //设置一个值
$this->notify();
}

public function getValue()
{
return $this->val;
}
}

//具体观察者
class user implements SplObserver
{
/**
* @param SplSubject $subject
* @return mixed
*/
public function update(SplSubject $subject)
{
if($subject->getValue() > 0)
{
echo '数字大于0<br/>';
}
else
{
echo '数字小于0<br/>';
}
}
}

$spl = new spl();
$spl->attach(new user());
$spl->setValue('1');
$spl->setValue('-1');

4.责任链模式

分配好各个层级的关系,可以很好地实现责任的扩展

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
header('content-type:text/html;charset=utf-8');
/**
* 版主类,首先提交到这里
* Class board
*/
class board
{
protected $power = 1;
protected $top = 'admin';

public function process($lev)
{
if($lev <= $this->power)
{
echo '版主删帖';
}
else
{
$top = new $this->top;
$top->process($lev);
}
}
}

class admin
{
protected $power = 2;
protected $top = 'police';

public function process($lev)
{
if($lev <= $this->power)
{
echo '管理员删帖';
}
else
{
//这里可以提交给上一级进行处理
echo '提交到更高一层';
}
}
}

$level = $_GET['level'] + 0;
$board = new board();
$board->process($level);

5.策略模式

下面是实现策略模式的代码,不直接创建具体的类,通过传递参数进行创建,自己以前使用的也比较多,只是没有了解这个策略模式

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
/**
* 策略模式
* Created by PhpStorm.
* User: Administrator
* Date: 2017/3/23
* Time: 10:55
*/
interface Math
{
public function calc($op1,$op2);
}
//加法
class MathAdd implements Math
{
/**
* @param $op1
* @param $op2
* @return mixed
*/
public function calc($op1, $op2)
{
return $op1 + $op2;
}
}
//减法
class MathSub implements Math
{
/**
* @param $op1
* @param $op2
* @return mixed
*/
public function calc($op1, $op2)
{
return $op1 - $op2;
}
}
//计算器类
class CMath
{
protected $calc = null;

/**
* CMath constructor.
*/
public function __construct($type)
{
$calc = 'Math'.$type;
$this->calc = new $calc();
}

public function calc($op1,$op2)
{
return $this->calc->calc($op1,$op2);
}
}

$math = new CMath($_GET['type']);
echo ($math->calc(1,2));

6.装饰者模式

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
class BaseArt
{
protected $content,$art;

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

public function decorator()
{
return $this->content;
}

}
//编辑添加文章摘要
class BianArt extends BaseArt
{
public function __construct(BaseArt $baseArt)
{
$this->art = $baseArt;
$this->decorator();
}

public function decorator()
{
return $this->content = $this->art->decorator().'小编摘要';
}
}
//seo人员添加seo
class SeoArt extends BaseArt
{
public function __construct(BaseArt $baseArt)
{
$this->art = $baseArt;
$this->decorator();
}

public function decorator()
{
return $this->content = $this->art->decorator().'seo';
}
}

$article = new SeoArt(new BianArt(new BaseArt('hello word')));
echo $article->decorator();
文章目录
  1. 1. 1.单例模式
  2. 2. 2.简单工厂模式 ###、
  3. 3. 3.工厂模式
  4. 4. 4.观察者模式
  5. 5. 4.责任链模式
  6. 6. 5.策略模式
    1. 6.1. 6.装饰者模式
|