前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php设计模式(二十二):模版方法模式(Template Method)

php设计模式(二十二):模版方法模式(Template Method)

作者头像
陈大剩博客
发布2023-07-09 14:03:27
1660
发布2023-07-09 14:03:27
举报

模版方法模式

模版方法模式又称为:Template Method。模板方法是一种行为设计模式,它在超类中定义了一个 算法(抽象方法) 的框架,允许子类在不修改结构的情况下重写 算法(抽象方法) 的特定步骤。

模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤

可能你已经见过这种模式很多次了,只是看不出来他是一种设计模式而已。它是一种让抽象模板的子类“完成”一系列算法的行为策略。它是一种非常适合框架库的算法骨架(抽象方法)。用户只需要实现子类的一种方法,其父类便可去完成这项工作。

问题

假设我们负责制作不同品牌 内存条,各种种品牌的内存条都包含:品牌、内存大小、内存颗粒类型、运行参数等。运行参数信息每种品牌都需要有且需要统一规范(CPU 才能读取信息),这样我们为每个品牌单独写了 品牌独立的类

一段时间后,我们发现这些各种 品牌独立的类 中包含 许多相似代码。尽管这些类品牌、内存大小、内存颗粒可能完全不同,但 获取参数运行 的代码却几乎完全一样。如果能在保持算法结构完整的情况下去除重复代码,这难道不是一件很棒的事情吗?

解决方法

我们将复杂的运行算法分解为一系列步骤,然后将这些步骤 改写为方法,最后在 “模板方法” 中依次调用这些方法。步骤可以是 抽象的,也可以有一些默认的实现。

对于完全相同的代码使用继承 抽象类 超类中的方法,不同的方法我们申请抽象方法,然后强制要求子类自行实现这些方法。

结构

Memory: 内存抽象类,定义操作中骨架;比如说执行顺序等;讲具体的执行内容延迟到子类; Samsung、SanDisk、Kingston:具体品牌内存子类,定义具体的执行内容;

代码示例

内存抽象类

代码语言:javascript
复制
/**
 * 内存抽象类
 */
abstract class Memory
{
    /**
     * 品牌
     * @return string
     * @author chendashe\ngpc
     */
    abstract public function brand(): string;

    /**
     * 内存大小
     * @return string
     * @author chendashengpc
     */
    abstract public function size(): string;

    /**
     * 运行参数
     * @return void
     * @author chendashengpc
     */
    public function config()
    {
        echo '内存品牌:' . $this->brand() . PHP_EOL;
        echo '内存大小:' . $this->size() . PHP_EOL;
        echo '内存颗粒:' . $this->particles() . PHP_EOL;
    }

    /**
     * 运行方法,运行是通用的。
     * @return void
     * @author chendashengpc
     */
    public function run()
    {
        echo '开始运行 ' . $this->brand() . ' 内存条' . PHP_EOL;
        $this->config();
        // do something
    }

    /**
     * 内存颗粒
     * @return void
     * @author chendashengpc
     */
    public function particles(): string
    {
        return 'TLC';
    }
}

具体子类

代码语言:javascript
复制
/**
 * 金士顿
 */
class Kingston extends Memory
{
    public function brand(): string
    {
        return '金士顿(Kingston)';
    }

    public function size(): string
    {
        return '8 Gb';
    }

    public function particles(): string
    {
        return 'MLC';
    }
}

/**
 * 三星
 */
class Samsung extends Memory
{
    public function brand():string
    {
        return '三星(Samsung)';
    }

    public function size():string
    {
        return '16 Gb';
    }
}

/**
 * 闪迪
 */
class SanDisk extends Memory
{
    public function brand(): string
    {
        return '闪迪(SanDisk)';
    }

    public function size(): string
    {
        return '8 Gb';
    }
}

客户端使用

代码语言:javascript
复制
/**
 * 金士顿
 */
$kingston = new Kingston();
$kingston->run();
echo PHP_EOL;

/**
 * 三星
 */
$samsung = new Samsung();
$samsung->run();
echo PHP_EOL;

/**
 * 闪迪
 */
$sandisk = new SanDisk();
$sandisk->run();
echo PHP_EOL;

输出

代码语言:javascript
复制
内存品牌:金士顿(Kingston)
内存大小:8 Gb
内存颗粒:MLC

内存品牌:三星(Samsung)
内存大小:16 Gb
内存颗粒:TLC

内存品牌:闪迪(SanDisk)
内存大小:8 Gb
内存颗粒:TLC

UML

模版方法模式
模版方法模式

优缺点

优点

  • 可仅允许客户端重写一个大型算法中的特定部分,使得算法其他部分修改对其所造成的影响减小。
  • 可将重复代码提取到一个超类中。

缺点

  • 部分客户端可能会受到算法框架的限制。
  • 通过子类抑制默认步骤实现可能会导致违反 里氏替换原则
  • 模板方法中的步骤越多, 其维护工作就可能会越困难。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 模版方法模式
  • 问题
  • 解决方法
  • 结构
  • 代码示例
    • 内存抽象类
      • 具体子类
        • 客户端使用
        • UML
        • 优缺点
          • 优点
            • 缺点
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档