从前端视角看设计模式之行为型模式篇

从前端视角看设计模式之创建型模式篇 "设计模式"源于GOF(四人帮)合著出版的《设计模式:可复用的面向对象软件元素》,该书第一次完整科普了软件开发中设计模式的概念,他们提出的设计模式主要是基于以下的面向对象设计原则: - 对接口编程而不是对实现编程 - 优先使用对象组合而不是继承 阅读详情

上篇我们介绍了 设计模式之结构型模式篇,接下来介绍设计模式之行为型模式篇

责任链模式

责任链模式允许将请求沿着一条链传递,直到有一个对象处理它为止。每个处理者都有机会处理该请求,或者将其传递给链中的下一个处理者,每个处理者只关心自己能处理的请求,而不关心请求的来源和链中的其他处理者


它的使用场景如下:

1)当有多个对象可以处理请求,且具体由哪个对象处理由运行时决定时

2)当需要向多个对象中的一个提交请求,而不想明确指定接收者时

3)在实际应用中,广泛应用于权限管理、审批流程等场景


责任链模式包含以下几个主要角色:

1)抽象处理者

负责定义处理请求的接口,通常包含一个指向下一个处理者的引用,若不能处理请求,则将请求传递给下一个处理者

2)具体处理者

继承自抽象处理者,实现具体的请求处理逻辑

3)客户端

向链上的处理者发出请求


通过以下这个审批系统来理解责任链模式,涉及多个审批角色,如经理、总监、CEO,每个角色都有不同的审批权限

1)定义请求类

包含请求的内容

// 定义请求类
class Request {
    constructor(amount, description) {
      this.amount = amount
      this.description = description
    }
}

2)定义抽象处理者

声明一个方法来处理请求,并定义一个指向下一个处理者的引用

// 定义抽象处理者类
class Approver {
    constructor(name) {
      this.name = name
      this.nextApprover = null // 下一位审批者
    }
    setNext(approver) {
      this.nextApprover = approver
    }
    // 处理请求的方法,具体逻辑由子类实现
    approve(request) {
      if (this.nextApprover) {
        this.nextApprover.approve(request)
      } else {
        console.log('没有审批者可以处理这个请求')
      }
    }
}

3)定义具体处理者

实现请求的处理逻辑,若无法处理则交给下一个处理者

// 定义具体处理者类:经理、总监、CEO
class Manager extends Approver {
    approve(request) {
      if (request.amount <= 1000) {
        console.log(`${this.name} 批准了 ${request.description},金额: ${request.amount}`)
      } else if (this.nextApprover) {
        console.log(`${this.name} 无权批准该请求,转交给 ${this.nextApprover.name}`)
        this.nextApprover.approve(request)
      }
    }
}
class Director extends Approver {
    approve(request) {
      if (request.amount <= 5000) {
        console.log(`${this.name} 批准了 ${request.description},金额: ${request.amount}`)
      } else if (this.nextApprover) {
        console.log(`${this.name} 无权批准该请求,转交给 ${this.nextApprover.name}`)
        this.nextApprover.approve(request)
      }
    }
} 
class CEO extends Approver {
    approve(request) {
      console.log(`${this.name} 批准了 ${request.description},金额: ${request.amount}`)
    }
}

4)客户端

创建并发出请求

// 客户端代码
const manager = new Manager('经理')
const director = new Director('总监')
const ceo = new CEO('CEO')

// 设定审批链:经理 -> 总监 -> CEO
manager.setNext(director)
director.setNext(ceo)

// 发起请求
const request1 = new Request(500, '购买办公设备')
manager.approve(request1)

const request2 = new Request(3000, '购买电脑')
manager.approve(request2)

const request3 = new Request(10000, '购买企业级服务器')
manager.approve(request3)

执行代码,运行结果如下:

在这里插入图片描述

命令模式

命令模式将一个请求封装为一个对象,从而可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作


它的使用场景如下:

1)当需要对行为进行记录、撤销/重做或事务处理时


命令模式包含以下几个主要角色:

1)命令

命令接口,声明一个执行操作的方法

2)具体命令

实现命令接口,负责执行具体操作,通常包含对接收者的引用,通过调用接收者的方法来完成请求的处理

3)接收者

知道如何执行与请求相关的操作,实际执行命令的对象

4)调用者

发送命令的对象,它包含了一个命令对象并能触发命令的执行,调用者并不直接处理请求,而是通过将请求传递给命令对象来实现

5)客户端

创建具体命令对象并设置其接收者,将命令对象交给调用者执行


通过以下这个遥控器控制家电来理解命令模式,将每一个开关的操作封装成命令对象,并通过遥控器来调用这些命令

1)命令接口

定义一个命令接口,包含一个执行方法execute()

// 定义命令接口
class Command {
    execute() {
      throw new Error("execute() 必须被实现")
    }
}

2)具体命令

实现命令接口,具体实现每个命令的操作

// 具体命令 - 开灯命令
class LightOnCommand extends Command {
    constructor(light) {
      super()
      this.light = light
    }
    execute() {
      this.light.turnOn()
    }
}
// 具体命令 - 关灯命令
class LightOffCommand extends Command {
    constructor(light) {
      super()
      this.light = light
    }
    execute() {
      this.light.turnOff()
    }
}
// 具体命令 - 开风扇命令
class FanOnCommand extends Command {
    constructor(fan) {
      super()
      this.fan = fan
    }
    execute() {
      this.fan.turnOn()
    }
}
// 具体命令 - 关风扇命令
class FanOffCommand extends Command {
    constructor(fan) {
      super()
      this.fan = fan
    }
    execute() {
      this.fan.turnOff()
    }
}

3)接收者

具体的家电设备(灯和风扇),每个设备都有开和关的操作

// 接收者 - 灯类
class Light {
    turnOn() {
      console.log("灯已打开")
    }
    turnOff() {
      console.log("灯已关闭")
    }
}
// 接收者 - 风扇类
class Fan {
    turnOn() {
      console.log("风扇已打开")
    }
    turnOff() {
      console.log("风扇已关闭")
    }
}

4)调用者

遥控器,通过调用命令对象的execute()方法来执行命令

// 调用者 - 遥控器类
class RemoteControl {
    constructor() {
      this.command = null
    }
    setCommand(command) {
      this.command = command
    }
    pressButton() {
      this.command.execute()
    }
}

5)客户端

客户端创建命令对象,并设置对应的设备

// 客户端代码
const light = new Light()
const fan = new Fan()

// 创建命令对象
const lightOn = new LightOnCommand(light)
const lightOff = new LightOffCommand(light)
const fanOn = new FanOnCommand(fan)
const fanOff = new FanOffCommand(fan)

// 创建遥控器
const remote = new RemoteControl()

// 按下按钮执行开关命令
remote.setCommand(lightOn)
remote.pressButton()  // 灯已打开

remote.setCommand(fanOn)
remote.pressButton()  // 风扇已打开

remote.setCommand(lightOff)
remote.pressButton()  // 灯已关闭

remote.setCommand(fanOff)
remote.pressButton()  // 风扇已关闭

解释器模式

解释器模式用于给定语言的句法(语法规则)提供一个解释器,这个解释器使用该表示来解释语言中的句子


它的使用场景如下:

1)当某一特定类型的问题频繁出现,并且可以通过一种简单的语言来表达这些问题的实例时

2)应用于编程语

从前端视角看设计模式之结构型模式篇 上篇介绍了设计模式之创建型模式,接下来介绍设计模式之结构型模式,这些模式关注对象之间的组合和关系,旨在解决如何构建灵活且可复用的类和对象结构 阅读详情

相关推荐

Spring⽤到了哪些设计模式

Spring 中大量使用设计模式以实现高内聚低耦合,最常见的包括:单例模式:Bean 默认是单例工厂模式:BeanFactory / ApplicationContext 解耦创建过程代理模式:AOP / 事务增强模板方法:JdbcTemplate 等封装主流程观察者模式:事件机制解耦通知策略模式:接口多实现动态挑选这些模式不是硬加进去的,而是融入架构设计的哲学中,体现了“开闭原则”、“依赖倒置”、“接口隔离”等设计原则。

完全体 757

从零开始掌握Simscape Multibody:机械系统建模与仿真入门

本文为机械系统建模与仿真入门指南,详细介绍了如何从零开始使用Simscape Multibody。通过构建曲柄摇块机构的实战案例,系统讲解了刚体、关节、约束等核心模块的使用,以及模型验证、参数化设计和多领域系统集成等进阶技巧,帮助工程师和学生高效进行虚拟设计与测试。

weixin_29229261的博客 310

LaMAR数据集下载和使用流程

LaMAR数据集

qq_51745206的博客 974

告别懵圈!用CANoe 5640手把手带你跑通SomeIP TC8测试(附脚本思路)

本文详细解析了基于CANoe 5640的SomeIP TC8测试全流程,从环境搭建到结果分析,特别针对车载以太网测试中的SomeIP协议测试难点提供实战指南。通过典型测试用例SOMEIP_TEST_61,手把手教你配置CANoe工程、编写CAPL脚本,并解决常见问题,助力开发者高效完成协议验证。

weixin_30791095的博客 363

InstallShield 打包 自定义安装依赖环境

用InstallShield2020打包.NetFramework4.5程序,程序需要集成Access数据库,必须安装AccessDatabaseEngine引擎,而InstallShield中自带的依赖项不包含该项,所以自定义集成了该依赖项。

zhaoziyu2020的博客 1128

闲鱼客户端三重动态签名机制解析:x-sign、x-mini-wua与x-umt

在移动客户端安全通信中,设备级动态签名已成为主流App防范自动化攻击的核心手段。其原理是将设备指纹、运行时行为与可信硬件标识深度融合,生成不可复用、不可跨端、不可静态伪造的请求凭证。这类机制超越传统Token或Session鉴权,具备强上下文绑定性与实时熵值校验能力,广泛应用于电商、社交及开放平台等高风险接口场景。技术价值体现在有效识别模拟器、无头浏览器与集群化爬虫,同时保障多端一致性与合规数据对接。本文聚焦闲鱼客户端实际落地的x-sign(带设备上下文的混合签名)、x-mini-wua(小程序行为水印)与

weixin_35732273的博客 497

Matterport3D数据集介绍与下载(全网最详细)

Matterport3D数据集介绍与下载(全网最详细)

shannanshouyin的博客 2171

对halcon形状匹配算法的一点分析

基于Intel VTune Profiler对halcon形状匹配算法的一点分析

manuoo的专栏 567

国债期货的日线趋势跟踪策略实现(基于backtrader框架)

通过backtrader框架,我们可以轻松地实现国债期货的日线趋势跟踪策略,并进行回测和验证。通过这种策略,我们可以尝试捕捉国债期货价格的短期趋势,并根据趋势的方向进行交易决策。backtrader提供了许多内置的指标、订单类型和其他功能,可以帮助你进一步优化和改进你的策略。它提供了丰富的工具和功能,使我们能够快速实现和验证我们的交易想法。方法中,我们根据当前价格和前一天的价格判断趋势的方向,并根据趋势的变化进行买入或卖出操作。然后,我们设置了初始资金和交易手续费,并将我们定义的策略。来跟踪每日的收盘价。

NisyPhilosophy的博客 404

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

上一篇: 从前端视角看设计模式之结构型模式篇
下一篇: JavaScript基础 -- 代理与反射
ZoeLandia
博客等级 码龄6年 734粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值