📜  策略模式 |第一套(介绍)

📅  最后修改于: 2021-09-10 02:52:56             🧑  作者: Mango

与往常一样,我们将通过定义问题并使用策略模式来解决它来学习这种模式。假设我们正在构建一个游戏“街头霸王”。为简单起见,假设一个字符可能有四个动作,即踢、拳、滚和跳。每个字符都有踢腿和出拳动作,但滚动和跳跃是可选的。你会如何建模你的类?假设最初您使用继承并抽象出Fighter类中的共同特征,并让其他字符继承Fighter类。

战斗机类将默认执行正常操作。任何具有特殊动作的字符都可以在其子类中覆盖该动作。类图如下:

战斗机1

上面的设计有什么问题?

如果字符不执行跳跃移动怎么办?它仍然继承了超类的跳转行为。尽管在这种情况下您可以覆盖 jump 以不执行任何操作,但是您可能必须为许多现有类这样做,并且也必须为以后的类处理这些问题。这也会使维护变得困难。所以我们不能在这里使用继承。

接口呢?

看看下面的设计: 战斗机2

干净多了。我们从Fighter类中取出了一些动作(某些字符可能不会执行)并为它们制作接口。这样,只有应该跳跃的字符才会实现JumpBehavior。

上面的设计有什么问题?

上述设计的主要问题是代码重用。由于没有跳跃和滚动行为的默认实现,我们可能会有代码重复。您可能必须在许多子类中一遍又一遍地重写相同的跳转行为。

我们怎样才能避免这种情况?

如果我们创建JumpBehaviorRollBehavior类而不是接口会怎样?那么我们将不得不使用由于与它相关的许多问题而在许多语言中都不支持的多重继承。

在这里,策略模式来拯救我们。我们将学习什么是策略模式,然后应用它来解决我们的问题。

定义:

维基百科将策略模式定义为:

“在计算机编程中,策略模式(也称为策略模式)是一种软件设计模式,可以在运行时选择算法的行为。策略模式

  • 定义了一系列算法,
  • 封装每个算法,和
  • 使算法在该系列中可以互换。”

 

图: 无标题

这里我们依靠组合而不是继承来重用。 ContextStrategy组成。 Context将其委托给Strategy ,而不是实现行为。上下文将是需要改变行为的类。我们可以动态地改变行为。策略是作为接口实现的,这样我们就可以在不影响上下文的情况下改变行为。

当我们使用它来解决我们的问题时,我们将对策略模式有更清晰的理解。

好处:

  1. 一系列算法可以定义为一个类层次结构,并且可以互换使用来改变应用程序行为而不改变其体系结构。
  2. 通过单独封装算法,可以很容易地引入符合相同接口的新算法。
  3. 应用程序可以在运行时切换策略。
  4. 策略使客户端能够选择所需的算法,而无需使用“switch”语句或一系列“if-else”语句。
  5. 用于实现算法的数据结构完全封装在 Strategy 类中。因此,可以在不影响 Context 类的情况下更改算法的实现。

缺点:

  1. 应用程序必须了解所有策略,以便为正确的情况选择正确的策略。
  2. Context 和 Strategy 类通常通过抽象 Strategy 基类指定的接口进行通信。策略基类必须公开所有必需行为的接口,某些具体的策略类可能无法实现。
  3. 在大多数情况下,应用程序使用所需的策略对象配置上下文。因此,应用程序需要创建和维护两个对象来代替一个对象。

 

参考:

  • Head First 设计模式
  • http://wiki.expertiza.ncsu.edu/index。 PHP/CSC/ECE_517_Fall_2007/wiki1b_8_sa
  • https://en.wikipedia.org/wiki/Strategy_pattern