这次给大家带来php模板方法模式使用详解,php模板方法模式使用的注意事项有哪些,下面就是实战案例,一起来看一下。
什么是模板方法模式
模板方法(template method)设计模式中使用了一个类方法templatemethod(), 该方法是抽象类中的一个具体方法, 这个方法的作用是对抽象方法序列排序,具体实现留给具体类来完成.关键在于模板方法模式定义了操作中算法的骨架,而由具体类来实现.
什么时候使用模板方法
如果已经明确算法中的一些步骤, 不过这些步骤可以采用多种不同的方法实现, 就可以使用模板方法调试.如果算法中的步骤不变, 可以把这些步骤留给子类具体实现.在这种情况下, 可以使用模板方法设计模式来组织抽象类中的基本操作(函数/方法).然后由子类来实现应用所需的这些操作.
还有一种用法稍微复杂一些, 可能需要把子类共同的行为放在一个类中, 以避免代码重复.
如果使用多个类来解决同一个大型问题, 可能很快就会出现重复代码.
还有一点,可以使用模板方法模式控制子类扩展,也就是所谓的钩子.
示例
在php编程中,可能经常会遇到一个问题: 要建立带图题的图像. 这个算法相当简单, 就是显示图像, 然后的图像下面显示文本.
由于模板设计中只涉及两个参与者, 所以这是最容易理解的模式之一, 同时也非常有用. 抽象建立templatemethod(),并由具体类实现这个方法.
抽象类
抽象类是这里的关键, 因为它同时包含具体和抽象方法. 模板方法往往是具体方法, 其操作是抽象的
两个抽象方法分别是addpicture和addtitile,这两个操作都包含一个参数, 分别表示图像的url信息和图像标题.
template.php
<?php
abstract class template
{
protected $picture;
protected $title;
public function display($picturenow, $titlenow)
{
$this->picture = $picturenow;
$this->title = $titlenow;
$this->addpicture($this->picture);
$this->addtitle($this->title);
}
abstract protected function addpicture($picture);
abstract protected function addtitle($title);
}
具体类
concrete.php
<?php
include_once('template.php');
class concrete extends template
{
protected function addpicture($picture)
{
$this->picture = 'picture/' . $picture;
echo "图像路径为:" . $this->picture . '<br />';
}
protected function addtitle($title)
{
$this->title = $title;
echo "<em>标题: </em>" . $this->title . "<br />";
}
}
客户
client.php
<?php
function autoload($class_name)
{
include $class_name . '.php';
}
class client
{
public function construct()
{
$title = "chenqionghe is a handsome boy";
$concrete = new concrete();
$concrete->display('chenqionghe.png', $title);
}
}
$worker = new client();
$concrete变量实例化了concrete, 但是它调用了display模板方法, 这是从父类继承的具体操作, 父类通过display()调用子类的操作.
运行后输出
图像路径为:picture/chenqionghe.png
标题: chenqionghe is a handsome boy
可以看到,客户只需要提供图像地址和标题
模板方法设计模式中的钩子
有时模板方法函数可能有一个你不想要的步骤, 某些特定情况下你可能不希望执行这个步骤, 这时候就可以用到模板方法的钩子.
在模板方法设计模式中, 利用钩子可以将一个方法作为模板的一部分,不过不一定会用到这个方法, 换句话说, 它是方法的一部分,不过它包含一个钩子, 可以处理例外情况. 子类可以为算法增加一个可选元素, 这样一来, 尽管仍按模板方法建立的顺序执行, 但有可能并不完成模板方法期望的动作. 对于这种可选的情况, 钩子就是解决这个问题最理想的工具.
示例
去网购商品, 登场8折, 如果总商品费用超过200元, 就免去12.95元钱运费.
建立钩子
在模板方法中建立钩子方法很有意思, 尽管子类可以改变钩子的行为, 但仍然要遵循模板中定义的顺序
ihook.php
<?php
abstract class ihook
{
protected $hook;
protected $fullcost;
public function templatemethod($fullcost, $hook)
{
$this->fullcost = $fullcost;
$this->hook = $hook;
$this->addgoods();
$this->addshippinghook();
$this->displaycost();
}
protected abstract function addgoods();
protected abstract function addshippinghook();
protected abstract function displaycost();
}
这里有3个抽象方法: addgoods(), addshippinghook(),displaycost(), 抽象类ihook实现的templatemethod()中确定了它们的顺序. 在这里, 钩子方法放在中间, 实际上模板方法指定的顺序中, 钩子可以放在任意位置. 模板方法需要两个参数, 一个是总花费, 另外还需要一个变量用来确定顾客是否免收运费.
实现钩子
一旦抽象类中建立了这些抽象方法, 并指定了它们执行的顺序, 子类将实现所有这3个方法:
concrete.php
<?php
class concrete extends ihook
{
protected function addgoods()
{
$this->fullcost = $this->fullcost * 0.8;
}
protected function addshippinghook()
{
if(!$this->hook)
{
$this->fullcost += 12.95;
}
}
protected function displaycost()
{
echo "您需要支付: " . $this->fullcost . '元<br />';
}
}
addgoods和displaycost都是标准方法, 只有一个实现., 不过, addshippinghook的实现有所不同, 其中有一个条件来确定是否增加运费. 这就是钩子.
客户client
client.php
<?php
function autoload($class_name)
{
include $class_name . '.php';
}
class client
{
private $totalcost;
private $hook;
public function construct($goodstotal)
{
$this->totalcost = $goodstotal;
$this->hook = $this->totalcost >= 200;
$concrete = new concrete();
$concrete->templatemethod($this->totalcost, $this->hook);
}
}
$worker = new client(100);
$worker = new client(200);
该client演示了分别购买100块钱和200块钱的商品最后的费用,运行结果如下
您需要支付: 92.95元
您需要支付: 160元
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
php接口隔离原则(isp)使用案例解析
php依赖倒置案例详解
以上就是php模板方法模式使用详解的详细内容。