php设计模式_模板模式

定义:
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。
模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模式结构
  1. 模板方法:
  • 一个模板方法是定义在抽象类中,把基本操作方法组合在一起形成一个总行为的方法;
  • 一个抽象类可以有任意多个模板方法,而不限于一个,每一个模板方法都可以调用任意多个具体方法;
  1. 基本方法:
  • 抽象方法:一个抽象方法由抽象类声明,由具体子类实现,抽象方法以 abstract 关键字修饰;
  • 具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换;
  • 钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展;
DEMO框架
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
<?php
//模板类
abstract class templete
{
//模板方法=>反向控制
function templateMethod($hook)
{
$this->before();
$this->doSomething();
$this->after();
//钩子方法
$this->hook = $spcial;
}
//抽象方法:强制子类实现
abstract function doSomething();

//一般方法
protected function before()
{
print "excute before\n";
}
//一般方法
protected function after()
{
print "excute after\n";
}
}

class class1 extends templete
{
public function doSomething()
{
print "class1 doSomething\n";
}

public function before()
{
//实现钩子
if ($this->hook) {
return false;
}
print "class1 before\n";
}
}

class class2 extends templete
{
public function doSomething()
{
print "class2 doSomething\n";
}
}

$class1Obj = new class1();
$class1Obj->templateMethod();

print "---------华丽的分割线------------\n";
$class2Obj = new class2();
$class2Obj->templateMethod();

运行结果

1
2
3
4
5
6
7
class1 before
class1 doSomething
excute after
---------华丽的分割线------------
excute before
class2 doSomething
excute after
场景:API接口的实现,4个步骤
  1. 参数解析:解析请求JSON为OBJ;
  2. 参数校验:针对参数进行过滤校验;
  3. 处理业务:业务逻辑的实现;
  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
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
//模板类
abstract class templete
{
//模板方法=>反向控制
protected function execute() {
//第一步:解析参数
$this->parseRequestParameter();
//第二步:校验参数
$this->checkRequestParameter();
//第三步:业务处理
$data = $this->doBusiness();
//第四步:组织返回参数
return $this->assembleResponseParameter($data);
}

protected function parseRequestParameter()
{
print "Template 解析参数 \n";
}

protected function checkRequestParameter()
{
print "Template 校验参数 \n";
}

//子类实现
protected abstract function doBusiness();
protected abstract function assembleResponseParameter($data);
}

class CreditApiController extends templete {

public function run()
{
return $this->execute();
}

public function parseRequestParameter()
{
print "Step1: CreditApiController 解析参数 \n";
}

public function checkRequestParameter()
{
print "Step2: CreditApiController 校验参数 \n";
}

public function doBusiness()
{
print "Step3: CreditApiController 处理业务 \n";

$dataObj = new ArrayObject (
['id' => 'No12345', 'name' => '张三']
);
return $dataObj;
}

public function assembleResponseParameter($data)
{
print("Step4: CreditApiController 返回参数 \n");

$result = new ArrayObject (
['code' => '200', 'data' => $data]
);
return $result;
}
}

$creditApiObj = new CreditApiController();
print_r($creditApiObj->run());
结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Step1: CreditApiController 解析参数 
Step2: CreditApiController 校验参数
Step3: CreditApiController 处理业务
Step4: CreditApiController 返回参数
ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[code] => 200
[data] => ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[id] => No12345
[name] => 张三
)
)
)
)
模板模式优缺点
优点
  1. 提高代码的复用性,将相同部分的代码放到抽象类里;
  2. 提高拓展性,将不同的放到不同的实现类里,通过实现类的扩展增加一些自己需要的行为;
  3. 实现反向控制,通过一个父类调用实现类的操作,通过对实现类的扩展增加新行为,实现反向控制;
缺点
  1. 因为使用了抽象类,每个不同的实现都需要一个子类来现实,这样会导致实现类的数量增多,从而导致系统实现的复杂度。
适用场景及优势
  1. 完成某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时。我们通常考虑用模板模式来处理。
  2. 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,我们通过模板模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。
  3. 模板模式通过把不变的行为搬移到超级抽象类,去除子类中的重复代码来体现它的优势。
-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!