设计模式是一个长期思考的问题,随着工作的使用,每一次看都会有新的理解。
感觉工厂类策略模式用的多一些,观察者很少用。其他的几乎用户到。
1.单例模式
为什么使用单例模式
- php的应用主要在于数据库应用, 一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时, 如果使用单例模式, 则可以避免大量的new 操作消耗的资源,还可以减少数据库连接这样就不容易出现 too many connections情况。
- 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分。
- 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中,
1 | class man |
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 |
|
使用了工厂类就可以不修改其他扩展地方代码的情况下,就行自由的扩展了。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
<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
46header('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 | class BaseArt |