设计模式 - JavaScript中的策略模式

63 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情

原文地址:dev.to/carlillo/de…

在这篇文章中,我将会讲解 Strategy Pattern 如何工作的,以及什么时候应该使用它,在其他文章中叫做 Policy

策略模式:基础概念

策略模式是一种行为设计模式,可以在运行时动态选择。 --Wikipedia

定义一系列类型、独立封装且可互相替换的算法,策略模式使算法不依赖使用它的客户。 -- Design Patterns: Elements of Reusable Object-Oriented Software

这种模式的主要特点就是调用方有一系列算法,在代码运行时会选择一个特定的。这些算法都是可以互相替换的。

下面的代码展示了一个典型的问题:在应用中,你需要选择一个具体算法。在代码中,你使用 switch 来控制编程需要的结构。

可是,使用策略模式,它可以变得更加灵活。就像下面的结构:

策略模式的 UML 图如下:

每个策略是使用一个具体的对象表示。所以,客户端/上下文包含一个实现了 Strategy 接口的 Strategy 对象。切换策略的关键存在于上下文中实现了一个切换策略的方法,例如:setStrategy

策略模式:何时使用

  1. 解决策略模式的问题是,当你需要使用几种有不同变化的算法时,你需要创建一个具体的类来实现你的算法(它可以由一个或几个函数组成)。
  2. 另一个你发现需要策略模式的有趣时刻是当有条件语句穿插在算法周围且它们之间还有联系时。
  3. 最后,你必须使用该模式时是你的多数类有相关的行为。

策略模式:优点

策略模式有许多优点,可以归纳为以下几点:

  • 运行时因为使用了接口的多态,所以很容易切换不同的算法。
  • 整洁的代码,因为你避免了条件语句代码(不复杂)。
  • 因为你把关注点分离到类中(每个策略的类)使得代码更整洁。

策略模式:用 JavaScript 简单实现

现在,我将用 JavaScript 给你演示如何实现一个策略模式,你肯定知道 JavaScript 缺乏接口。所以,你需要编写一个 StrategyManager 类用作接口。

这个类包含私有的属性 _strategy ,用它代表将被使用的策略。doAction 方法将会被每个具体的策略实现。JavaScript 中的策略模式与 UML 图不同是因为缺乏语言级别的 OOP 特性。

每个具体的策略实现如下:

注意具体的 doAction 方法是在每个具体的策略中实现的。

最后,用户端/上下文必须包含 StrategyManager 来使用具体的策略:

策略模式:用 JavaScript 实现的多个策略

在接下来的实现中,我们的 StrategyManager 会更复杂以及包含一系列算法。在这种场景下,你可以用数组 _strategies 来代替 _strategy 属性。

最后,你可以通过 addStrategy 想列表添加新策略。一个策略类包含 2 个属性:1) 策略名字;2) 算法(又叫 处理器)。doAction 是用来调用具体策略算法的方法。

最后,用户端/上下文的代码使用具体策略的位置如下:

代码的第一部分是来创建具体的策略(可以通过 Singleton 模式和 Factory 模式),接着被添加到我们的 strategyManager 中。接下来是上下文选择策略来使用,在我们应用中策略可以通过 GUICLI 来选择。

最后,你会意识到若选择了一个没有支持的策略系统将会报错。当你想为你的系统提供一个高级算法时,可以使用这个方法。

总结

策略模式是一种当需要选择一个具体算法时,可以使你代码避免复杂的模式。在这篇文章中,你知道了通过缺乏接口的 JavaScript 实现的策略模式。在你使用的语言支持接口的场景下,你可以跟随 UML 图来实现。

最重要的不是我所实现的策略模式方法,而是你需要知道这个模式解决的是什么问题,以及为什么你必须使用这个模式。因为编程语言不同,实现也就不同。