陈大剩博客

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

  • 陈大剩
  • 2023-06-12 10:11:42
  • 700

模版方法模式

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

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

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

问题

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

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

解决方法

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

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

结构

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

代码示例

内存抽象类

/**
 * 内存抽象类
 */
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';
    }
}

具体子类

/**
 * 金士顿
 */
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';
    }
}

客户端使用

/**
 * 金士顿
 */
$kingston = new Kingston();
$kingston->run();
echo PHP_EOL;

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

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

输出

内存品牌:金士顿(Kingston)
内存大小:8 Gb
内存颗粒:MLC

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

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

UML

模版方法模式

优缺点

优点

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

缺点

  • 部分客户端可能会受到算法框架的限制。
  • 通过子类抑制默认步骤实现可能会导致违反 里氏替换原则
  • 模板方法中的步骤越多, 其维护工作就可能会越困难。
分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[109]| 评论总数[9]| 登录用户[22]| 时间点[112]

logo

登入

社交账号登录