js 函数如何实现策略模式与状态模式

这篇具有很好参考价值的文章主要介绍了js 函数如何实现策略模式与状态模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

有关设计模式的学习资料中,大部分都是以 java 语言实现的,毕竟 java 作为老牌面向对象的语言最能说明设计模式的核心概念,所以 js 的相关设计模式的学习资料也大多使用 class 类实现,本文记录下 js 使用函数实现策略模式和状态模式设计模式的方式,更有助于理解策略模式和状态模式如何在实际工作中运用。

策略模式

定义一系列的算法,把它们一个一个封装起来,并且使它们可以相互替换。

目的:将算法的使用和算法实现分离开来

优点:

  • 利用组合、委托、多态等思想,可以解决多重条件选择语句问题
  • 策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展
  • 策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作
  • 在策略模式中利用组合和委托来让 Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案

缺点:

  • 代码会增加许多策略类和策略对象
  • 需要全面了解各种 stragety, stragety要向客户暴露它的所有实现,违反最少知识原则

状态模式

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

优点:

  • 状态模式定义了状态与行为之间的关系,并将它们封装在一个类里。通过增加新的状态类,很容易增加新的状态和转换
  • 避免 Context 无限膨胀,状态切换的逻辑被分布在状态类中,也去掉了 Context 中原本过多的条件分支
  • 用对象代替字符串来记录当前状态,使得状态的切换更加一目了然
  • Context 中的请求动作和状态类中封装的行为可以非常容易地独立变化而互不影响

缺点:

  • 会在系统中定义许多状态类,而且系统中会因此而增加不少对象

         性能优化点

    • 1、仅当 state 对象被需要时才创建并随后销毁,用于节省内存,但不常变动的
    • 2、一开始就创建好所有的状态对象,并且始终不销毁它们,用于状态经常变动的
  • 由于逻辑分散在状态类中,虽然避开了不受欢迎的条件分支语句,但也造成了逻辑分散的问题,我们无法在一个地方就看出整个状态机的逻辑

相同点

  • 都有一个上下文、一些策略或状态类
  • 上下文把请求委托给这些类来执行

区别

状态模式

  • 【不同事情 】状态模式各状态之间的切换,做不同的事情;
  • 【不能互相替换 】状态模式各个状态的同一方法做的是不同的事,不能互相替换,状态和状态行为是早已被封封装好的,状态之间的切换也早被规定完成,改变模式这个行为发生在状态内部,使用者不需要了解改变的细节;
  • 【封装状态】状态模式封装了对象的状态;
  • 【状态不可重用】因为状态是跟对象密切相关的,它不能被重用;
  • 【持有context 】在状态模式中,每个状态通过持有Context的引用,来实现状态转移;。

策略模式

  • 【同样的事情】策略模式更侧重于根据具体情况选择策略,做同样的事情;
  • 【可替换】策略模式各个策略之间是可替换的,平等又平行,互相之间没有任何联系,需熟知各个策略、各类的作用,以便随时切换算法;
  • 【封装算法和策略】策略模式封装算法或策略;
  • 【策略可重用】策略模式通过从Context中分离出策略或算法,我们可以重用它们;
  • 【不持有context】但是每个策略都不持有Context的引用,它们只是被Context使用。context持有对某个策略对象的引用。
状态模式关注于对象的状态转换,而策略模式关注于将算法或行为封装到策略对象中,以便在运行时动态替换。

联系

状态模式和策略模式都是为具有多种可能情形设计的模式,把不同的处理情形抽象为一个相同的接口,符合对扩展开放,对修改封闭的原则。(优化多个条件判断语句的业务逻辑)

实践

策略模式

var S = function( salary ){ 
  return salary * 4; 
}; 
var A = function( salary ){ 
  return salary * 3; 
}; 
var B = function( salary ){ 
  return salary * 2; 
}; 
// 这里的 context 是 calculateBonus
var calculateBonus = function( func, salary ){ 
  return func( salary ); 
}; 
calculateBonus( S, 10000 ); // 输出:40000
// 定义各个策略对象,每个策略对象都不持有 context 的引用,仅仅被 context 使用
const add = {
  calculate: function (a, b) {
    return a + b;
  },
};

const subtract = {
  calculate: function (a, b) {
    return a - b;
  },
};

const multiply = {
  calculate: function (a, b) {
    return a * b;
  },
};

// 策略管理器,这里 Calculator 代表了 context,context 拥有执行不同算法的能力,传参为要执行的策略,context 持有对某个策略对象的引用
function Calculator(strategy) {
  this.strategy = strategy;

  this.setStrategy = function (newStrategy) {
    this.strategy = newStrategy;
  };

  this.calculate = function (a, b) {
    return this.strategy.calculate(a, b);
  };
}

// 使用
// 传入或设置不同的策略,执行结果函数得到结果
const calculator = new Calculator(add);
console.log(calculator.calculate(2, 3)); // 5
calculator.setStrategy(subtract);
console.log(calculator.calculate(2, 3)); // -1
calculator.setStrategy(multiply);
console.log(calculator.calculate(2, 3)); // 6

状态模式

/ 状态对象
// 每个状态对象持有对传入状态的引用,以便流转至下一个状态
const redLight = {
  name: '红灯',
  nextState: function () {
    return greenLight;
  },
};

const yellowLight = {
  name: '黄灯',
  nextState: function () {
    return redLight;
  },
};

const greenLight = {
  name: '绿灯',
  nextState: function () {
    return yellowLight;
  },
};

// 状态管理器
function TrafficLightManager(initialState) {
  this.state = initialState;

  this.changeState = function () {
    this.state = this.state.nextState();
  };
}

// 使用
// 传入初始状态
const trafficLight = new TrafficLightManager(redLight);
console.log(trafficLight.state.name); // 红灯
// 通过状态流转方法切换下一个状态
trafficLight.changeState();
console.log(trafficLight.state.name); // 绿灯
trafficLight.changeState();
console.log(trafficLight.state.name); // 黄灯
// 封装执行状态的请求
var delegate = function (client, delegation) {
  return {
    buttonWasPressed: function () { // 将客户的操作委托给 delegation 对象
      return delegation.buttonWasPressed.apply(client, arguments);
    }
  }
};

// 定义状态机
var FSM = {
  off: {
    buttonWasPressed: function () {
      console.log('关灯');
      this.button.innerHTML = '下一次按我是开灯';
      this.currState = this.onState;
    }
  },
  on: {
    buttonWasPressed: function () {
      console.log('开灯');
      this.button.innerHTML = '下一次按我是关灯';
      this.currState = this.offState;
    }
  }
};

// 这里 Light 代表了 context,context 持有各个状态对象的引用,根据状态的改变执行不同的行为
var Light = function () {
  this.offState = delegate(this, FSM.off);
  this.onState = delegate(this, FSM.on);
  this.currState = this.offState; // 设置初始状态为关闭状态
  this.button = null;
};

Light.prototype.init = function () {
  var button = document.createElement('button'),
    self = this;
  button.innerHTML = '已关灯';
  this.button = document.body.appendChild(button);
  this.button.onclick = function () {
    self.currState.buttonWasPressed();
  }
};

var light = new Light()

 

本文大部分总结自书《javascript设计模式与开发实践》,仅供学习使用,如有错误,望大家多多指正。文章来源地址https://www.toymoban.com/news/detail-710770.html

到了这里,关于js 函数如何实现策略模式与状态模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • js设计模式:策略模式

    根据不同的条件去进行相应的业务逻辑处理 就好比针对每种情况都制定对应的方案,触发条件就启动某项方案策略

    2024年02月20日
    浏览(33)
  • 【强化学习入门】二.强化学习的基本概念:状态、动作、智能体、策略、奖励、状态转移、轨迹、回报、价值函数

    超级玛丽游戏中,观测到的这一帧画面就是一个 状态(State) 。 玛丽做的动作:向左、向右、向上即为 动作(Action) 。 动作是由谁做的,谁就是 智能体(Agent) 。自动驾驶中,汽车就是智能体;机器人控制中,机器人就是智能体;超级玛丽游戏中,玛丽就是智能体。 策略

    2024年02月03日
    浏览(35)
  • 【设计模式与范式:行为型】61 | 策略模式(下):如何实现一个支持给不同大小文件排序的小程序?

    上一节课,我们主要介绍了策略模式的原理和实现,以及如何利用策略模式来移除 if-else 或者 switch-case 分支判断逻辑。今天,我们结合“给文件排序”这样一个具体的例子,来详细讲一讲策略模式的设计意图和应用场景。 除此之外,在今天的讲解中,我还会通过一步一步地

    2024年02月10日
    浏览(32)
  • js中如何实现一个简单的防抖函数?

    前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一

    2024年02月09日
    浏览(36)
  • 4.设计模式之后七种模式后11种模式命令访问者迭代器发布订阅中介者忘备录解释器状态策略职责链和空模式

    1.命令(command)模式 不知道命令接收者(对象)是谁,支持撤销 (接受者 间接调用执行 的具体行为) 命令调用者和接收者解耦 //只要实现命令接口即可 (就是客户端给个命令,然后命令类传给接收类执行) 优点和缺点 容易撤销操作 命令队列可以多线程操作 增加过多的命令类 空命令也

    2024年02月12日
    浏览(40)
  • 如何利用产品状态维度优化库存管理和采购策略?【ODOO15/16】

           ODOO产品属性有个分类维度值,很多人不明白具体该怎么用?其实用处很大,我们首先要确立一个观点:没有分类就没有管理!公司里那么多产品,都有不同的特性、用途、价值,我们只有进行准确分类,才能针对性的管理。       ODOO的分类设置界面:      以下我

    2024年02月07日
    浏览(26)
  • Visual C++中的虚函数和纯虚函数(以策略设计模式为例)

    我是荔园微风,作为一名在IT界整整25年的老兵,今天来说说Visual C++中的虚函数和纯虚函数。该系列帖子全部使用我本人自创的对比学习法。也就是当C++学不下去的时候,就用JAVA实现同样的代码,然后再用对比的方法把C++学会。 直接说虚函数和纯虚函数有很多人会直接晕,但

    2024年02月12日
    浏览(37)
  • 【JAVA】有关时间的操作在编程中如何实现?

    个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 在许多应用程序中,日期和时间的处理是必不可少的。Java提供了一套强大的日期和时间API,使开发人员能够轻松地处理日期和时间的各种操作。今天我们主要来介绍一些JAVA中关时间的类。 java.util 包提供了 Date 类来封

    2024年02月13日
    浏览(25)
  • 【面试题】如何理解 前端设计模式-测策略模式?

    前端面试题库 ( 面试必备)              推荐:★★★★★ 地址:前端面试题库 【国庆头像】- 国庆爱国 程序员头像!总有一款适合你! 策略(Strategy)模式的定义:该模式定义了一 系列算法 ,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响使用

    2024年02月07日
    浏览(33)
  • 状态模式揭秘-如何优雅地处理复杂状态转换

    ​🌈 个人主页: danci_ 🔥 系列专栏: 《设计模式》 💪🏻 制定明确可量化的目标,并且坚持默默的做事。 探索设计模式的魅力:状态模式揭秘-如何优雅地处理复杂状态转换     状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变它的行为。这个模式使得

    2024年03月15日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包