设计模式 - 模板方法
原著中描述了23种经典的设计模式Design Patterns: Elements of Reusable Object-Oriented Software
。这些模式
为软件
开发中经常重复出现的特定问题提供了解决方案。
在本文中,我将描述模板模式;以及如何
以及何时应用它。
模板方法模式:基本思想
模板方法模式是一种行为 设计模式,它定义操作中算法的程序骨架,将一些步骤推迟到子类——维基百科
定义操作中算法的框架,将某些步骤推迟到子类。模板方法允许子类
在不改变算法结构的情况下重新定义算法的某些步骤。——《设计模式:可复用面向对象软件的要素》
此模式的主要特点是算法在
不同类型的类之间略有不同。
在具体类中实现时,这些共同的部分会在不同的算法中重复出现。
最初于 2019 年 3 月 1 日在www.carloscaballero.io上发布。
下面的代码展示了一个经典问题,你必须重复
算法的某些部分(复制/粘贴),并且只做很小的改动:
我们可以使用模板方法模式使代码更加简洁,这样可以避免在
算法的不同实现中重复代码。该模式的 UML 图如下:
注意抽象类,它包含模板方法和
共有的私有方法。模板方法以不同的步骤描述算法。
共有的步骤在抽象类中实现,而每个具体类中不同的具体
步骤则在该具体类中实现。
模板方法模式:何时使用
- 模板方法模式解决的问题是使用具有不同变体的算法。您需要将算法拆分成不同的步骤,如果不同的实现之间有共同点,则在抽象类中实现。相反,不同的步骤将在具体类中实现。
- 另一个有趣的情况是,当您在不同的类之间复制/粘贴代码(私有函数)时,您会发现这种模式的需要。
- 最后,当大多数类都有相关行为时,您可以使用这种模式。
模板方法模式:优点
模板方法模式有几个优点,总结如下
几点:
- 创建算法的具体实现相当容易,因为您可以通过使用抽象类删除问题域的公共部分。
- 清理代码,因为您避免了重复的代码。
- 代码更加简洁,因为您将算法分成私有方法/函数,它们更简单且更易于测试。
模板模式:使用 JavaScript 的 Pokemon 示例
现在我将向您展示如何使用 JavaScript 实现此模式。请
记住,Javascript 缺少接口和抽象类。
因此,理解此模式的最佳方法是使用示例。在
我们的例子中,我想到了一个问题,其中有一个名为的抽象类,它定义了一个 Pokemon。除了经典方法之外, Pokemon
Pokemon 还有一组属性,例如name
,和。Pokemon 的类型有分类,例如power
,和,它们定义了一个名为的具体方法,该方法根据属性和 Pokemon 的类型计算数值。下面的 UML 图展示了我 刚才描述的 场景。attack
defense
toString
FightingPokemon
PoisonPokemon
GroundPokemon
calculateDamage
使用JavaScript实现实际情况的代码如下
:
该方法calculateDamage
在每个具体类中重复,即
存在异味代码(复制/粘贴 - 重复代码)。该方法可以分为
不同的步骤,如下所示:
请注意,我们的方法被分为三个功能。实际上,两个是
通用的,一个是特定的,具体取决于实现它的类
(calculateImpact
)。我们的Template-Method
模式已成功应用。
在下面的 UML 中,您可以看到使用模板方法进行的版本更新。
该类Pokemon
如下:
this.calculateImpact
你可能已经注意到,这个类中没有实现method方法
。这是因为具体的实现将
在具体类中实现。在我们的问题中,这个 Pokemon 类是抽象类。
下一步包括实现具有
该calculateImpact
方法的具体类。
最后,我们使用具体 Pokemon 的客户端/上下文代码如下
:
这段代码创建了具体的 Pokemon,并调用了它的calculateDamage
。它的
实现对客户端/上下文透明,但代码不会重复。最后,我创建了两个 npm 脚本,分别在 应用模板方法模式
之前和之后运行代码。
npm run step0
npm run step1
结论
模板方法模式是一种避免
项目中代码重复的模式,当一个算法同时包含不变部分和可变部分时,后者
取决于具体的类。在本文中,您已经观察到一个
使用 JavaScript 语言的简单实现,该语言缺少
接口/抽象。如果您使用的编程语言具有
接口/抽象,则可以遵循 UML 模式。
最重要的不是按照我展示的方式实现模式,而是
能够识别这个特定模式能够解决的问题,以及
何时应该实现或不应该实现该模式。这一点至关重要,因为
具体实现会根据你使用的编程语言而有所不同。
最初于 2019 年 3 月 1 日在www.carloscaballero.io上发布。
文章来源:https://dev.to/carlillo/design-patterns---template-method-180k