前言
根据 GOF 一书,行为型设计模式共有十一种。
行为型模式:策略模式
、模板方法模式
、观察者模式
、迭代子模式
、责任链模式
、命令模式
、备忘录模式
、状态模式
、访问者模式
、中介者模式
、解释器模式
。
十一种行为型设计模式可以大致分为四类:
- 父类与子类关系
- 两个类之间
- 类的状态
- 通过中间类
本文主要是介绍第一类行为型设计模式
父类与子类关系:
- 策略模式 (Strategy Pattern)
- 模板模式 (Template Pattern)
PHP设计模式(十二)—策略模式 ( Strategy Pattern )
策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)
(一)为什么需要策略模式
1,在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
2,利用面向对象的继承和多态机制,将多个算法解耦。避免类中出现太多的if-else语句
(二)策略模式 UML图
Context(应用场景):
1、需要使用ConcreteStrategy提供的算法。
2、 内部维护一个Strategy的实例。
3、 负责动态设置运行时Strategy具体的实现算法。
4、负责跟Strategy之间的交互和数据传递。
Strategy(抽象策略类):
定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。
ConcreteStrategy(具体策略类):
实现了Strategy定义的接口,提供具体的算法实现。
(三)简单实例
如果我们现在在做一个商城,用户来了,我们想向其推荐对应的商品。比如说一个女性用户登录的话,我们就问她需要衣服,男性用户就推荐螺丝刀,不确定性别就推荐《葵花宝典》
<?php
//抽象策略接口
abstract class Strategy{
abstract function peddle();
}
//具体封装的策略方法 女性用户策略
class ConcreteStrategyA extends Strategy
{
public function peddle(){
echo '美女穿这件衣服肯定很好看'.PHP_EOL;
}
}
//男性用户策略
class ConcreteStrategyB extends Strategy
{
public function peddle(){
echo '每一个男人都需要一个工具箱,充实工具箱,从购买各种螺丝刀开始'.PHP_EOL;
}
}
//未知性别用户策略
class ConcreteStrategyC extends Strategy
{
public function peddle(){
echo '骨骼清奇,这本《葵花宝典》最适合你'.PHP_EOL;
}
}
//环境类
class Context{
protected $strategy;
public function __construct(Strategy $strategy)
{
$this->strategy = $strategy;
}
public function request()
{
$this->strategy->peddle($this);
}
}
//若处于女性用户环境
$female_context = new Context(new ConcreteStrategyA);
$female_context->request();
//若处于男性用户环境
$male_context = new Context(new ConcreteStrategyB);
$male_context->request();
//若处于未知性别用户环境
$unknow_context = new Context(new ConcreteStrategyC);
$unknow_context->request();复制代码
这里我们可以看到,我们可以通过不同的环境选择不同的策略,用户性别的判断 如果对于一个商城系统来说,完全可以在用户登陆的时候通过数据库的用户信息得到,然后做出判断,选择适合的策略。
而且策略模式最显而易见的优势,就是如果我想增加一个新的策略怎么办?比如说,如果用户是小孩,就给他推荐《五年中考三年模拟》。是的,相信你们心里已经有答案了。那就是,再增加一个具体策略类。
PHP设计模式(十三)—模板模式(Template Pattern)
模板模式 (Template Pattern): 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
(一)为什么需要模板模式
1,一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2, 多个子类有相同的方法,逻辑基本相同时。可将相同的逻辑代码提取到父类
3,重构时,将相同代码抽取到父类,然后通过钩子函数约束其行为
(二)模板模式 UML图
(三)简单实例
这里举《PHP设计模式》的一个例子:一个银行可以有许多不同类型的银行账户,但是所有账户的处理方式基本相同。假设我们现在有两类账户,一类是普通账户,一类是信用卡账户。现在进行支付,信用卡允许透支,普通账户不允许透支,即账户金额不允许小于零
<?php
//抽象模板类
abstract class Template{
protected $balance = 100; //账户余额,为测试方便,直接赋初值100
//结算方法
abstract protected function adjust($num);
//支付信息显示
abstract protected function display($num);
final public function apply($num){
$this->adjust($num);
$this->display($num);
}
}
//普通账户
class Account extends Template{
protected $falg; //用于判断支付是否成功
protected function adjust($num){
if($this->balance > $num){//只有余额大于所需支付金额才允许支付
$this->balance-=$num;
$this->falg = true;
}else{
$this->falg = false;
}
}
protected function display($num){
if($this->falg){
echo '支付成功,所剩余额为'.$this->balance.PHP_EOL;
}else{
echo '余额不足,支付失败,所剩余额为'.$this->balance.PHP_EOL;
}
}
}
//信用卡用户
class Credit extends Template{
protected function adjust($num){
$this->balance-=$num;
}
protected function display($num){
echo '感谢您使用信用支付,所剩余额为'.$this->balance.PHP_EOL;
}
}
//普通账户使用
$account = new Account;
//普通账户使用
$account -> apply(80);
//普通账户透支
$account -> apply(30);
//信用卡账户使用
$credit = new Credit;
$credit -> apply(200);复制代码
模板模式的好处在于行为由父类控制,而具体的实现由子类实现。这就可以把一个操作延迟绑定到子类上。还有另一种应用是把复杂的核心代码设计为模板方法,周边的相关细节则由子类实现。
上一篇:PHP结构型设计模式(下)
感谢阅读,由于笔者也是初学设计模式,能力有限,文章不可避免地有失偏颇
后续更新 PHP行为型设计模式(二)介绍,欢迎大家评论指正
我最近的学习总结: