Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

行为型模式-策略模式 #45

Open
hawtim opened this issue Oct 10, 2020 · 0 comments
Open

行为型模式-策略模式 #45

hawtim opened this issue Oct 10, 2020 · 0 comments

Comments

@hawtim
Copy link
Owner

hawtim commented Oct 10, 2020

定义

定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化

目的

目的是将算法的使用和算法的实现分离开。

组成

策略模式至少包含两个部分:

  1. 第一部分是一组策略类,封装了具体的算法,负责具体的计算过程。
  2. 第二个部分是环境类 context,接受客户的请求,随后把请求委托给某一个策略类。

一个计算奖金的例子

我们首先来看基于传统面向对象语言的模仿,各个类的职责体现得更加鲜明。

class performanceS {
  calculate(salary) {
    return salary * 4
  }
}
class performanceA {
  calculate(salary) {
    return salary * 3
  }
}
class performanceB {
  calculate(salary) {
    return salary * 2
  }
}

class Bonus {
  constructor() {
    this.salary = null
    this.strategy = null
  }
  setSalary(salary) {
    this.salary = salary
  }
  setStrategy(strategy) {
    this.strategy = strategy
  }
  getBonus() {
    return this.strategy.calculate(this.salary)
  }
}

let bonus = new Bonus()

bonus.setSalary(10000)
bonus.setStrategy(new performanceS())
console.log(bonus.getBonus()) // 输出 40000
bonus.setStrategy(new performanceA())
console.log(bonus.getBonus()) // 输出 30000

JavaScript 版本的策略模式(不需要用到类的概念)

在JavaScript的策略模式中,策略类往往基于函数实现,因此策略模式在 JS 中是”隐形“的,我们通过高阶函数封装不同的行为,并把它传递到另一个函数(策略类)中,当我们调用这些高阶函数时,不同的函数调用返回不同的结果。

let strategies = {
  "S": function(salary) {
    return salary * 4
  },
  "A": function(salary) {
    return salary * 3
  },
  "B": function(salary) {
    return salary * 2
  }
}

let calculateBonus = function(level, salary) {
  return strategies[level](salary)
}

console.log(calculateBonus('S', 20000))
console.log(calculateBonus('A', 10000))

优点:

  • 策略模式有效避免多重条件选择语句
  • 提供了对开放-封闭原则的完美支持,使得易于切换,理解、扩展。
  • 利于算法复用,符合 DRY 原则
  • 利用组合和委托让 Context(最终将算法执行的方法)拥有执行算法的能力

缺点:

  • 会增加许多策略类或者策略对象,可以通过享元模式在一定程度上减少。
  • 客户要使用策略模式,必须暴露所有策略的实现,违反了最少知识原则。

应用场景

  • 如果许多类之间的区别仅在于它们的行为,那么使用策略模式可以动态地让对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
  • 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。

总结

  • 策略模式是一种行为型模式,也称为政策模式(Policy)。
  • 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略,在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在抽象策略类中定义的算法(JavaScript中没有抽象类)

参考

策略模式

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant