写点什么

ES6 类聊 JavaScript 设计模式之行为型(一)

作者:devpoint
  • 2022 年 7 月 26 日
  • 本文字数:3550 字

    阅读完需:约 12 分钟

ES6 类聊 JavaScript 设计模式之行为型(一)

本文将对 20 多种 JavaScript 设计模式进行简单概述,然后结合 ES6 类的方式来编写实例代码展示其使用方式。


JavaScript 在现代前端中扮演重要的角色,相比过去能够做的事情已经不在一个级别上了。JavaScript 最大的特征是其灵活性,一般只要敢想敢写,可以把程序写得很简单,有可以写得很复杂。其灵活性导致编写 JavaScript 的时候能够不断的优化,能够不断质疑写的质量。而设计模式,是不分编程语言的,是软件工程的内容,JavaScript 强大的表现力赋予了开发者运用设计模式编写代码时创造性。

什么是设计模式?

设计模式是软件设计中常见问题的解决方案,这些模式很容易重复使用并且富有表现力。


在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。它并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。面向对象设计模式通常以类别或对象来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类别或对象。—— 维基百科


在 JavaScript 中使用设计模式主要有以下原因:


  1. 可维护性:设计模式有助于降低模块间的耦合程度。

  2. 沟通:设计模式为处理不同类型的对象提供了一套通用的术语。

  3. 性能:对代码起到优化作用,提高程序的运行速度。当然不是所有的设计模式都能够改善性能。


有三种模式:创建型模式,结构型模式、行为型模式。


  • 创建型模式:解决与创建对象相关的问题。

  • 结构型模式:处理实体之间的关系,以及它们如何共同组成一个更大的结构。

  • 行为型模式:处理对象如何相互通信和交互。


系列文章:


行为型设计模式

行为设计模式特别关注对象之间的通信。


在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。—— 维基百科


  • 责任链模式

  • 命令模式

  • 迭代器模式

  • 中介者模式

  • 备忘录模式

  • 观察者模式

  • 访问者模式

  • 策略模式

  • 状态模式

  • 模板方法

13. 责任链模式

责任链模式创建了一个对象链,从一个点开始,它会停止,直到找到某个条件。


为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。—— 维基百科

实例

实例将使用一个生物攻击防御的游戏。游戏中生物将增加它的防御和攻击当它到达一定的点。它会形成一个链条,攻击和防御会增加和减少。


class Creature {    constructor(name, attack, defense) {        this.name = name;        this.attack = attack;        this.defense = defense;    }
toString() { return `${this.name} (攻击值:${this.attack} / 防御值:${this.defense})`; }}class CreatureModifier { constructor(creature) { this.creature = creature; this.next = null; }
add(modifier) { if (this.next) { this.next.add(modifier); } else { this.next = modifier; } }
handle() { if (this.next) { this.next.handle(); } }}
// 增加攻击逻辑class DoubleAttackModifier extends CreatureModifier { constructor(creature) { super(creature); }
handle() { console.log(`来自 ${this.creature.name} 的双重攻击!`); this.creature.attack *= 2; super.handle(); }}
// 增加防御逻辑class IncreaseDefenseModifier extends CreatureModifier { constructor(creature) { super(creature); }
handle() { if (this.creature.attack <= 2) { console.log(`增加 ${this.creature.name} 的防御!`); this.creature.defense++; } super.handle(); }}
复制代码


接下来看下如何使用责任链模式定义的类。


const bacteria = new Creature("Bacteria", 1, 1); console.log(bacteria.toString()); // Bacteria (攻击值:1 / 防御值:1)const root = new CreatureModifier(bacteria);root.add(new DoubleAttackModifier(bacteria));root.add(new IncreaseDefenseModifier(bacteria));root.handle(); // 来自 Bacteria 的双重攻击! // 增加 Bacteria 的防御!console.log(bacteria.toString()); // Bacteria (攻击值:2 / 防御值:2)
复制代码

14. 命令模式

命令模式将创建将动作封装在对象中的对象。


在面向对象的编程中,命令模式是一种行为设计模式,其中对象用于封装执行操作或稍后触发事件所需的所有信息。这些信息包括方法名称、拥有该方法的对象和方法参数的值。 —— 维基百科

实例

代码实例将举一个银行帐户的需求,假如必须存入或提取一定数量的钱,会在其中发出命令。


class BankAccount {    constructor(balance = 0) {        this.balance = balance;    }
deposit(amount) { this.balance += amount; console.log(`账户存入:${amount},余额为:${this.balance}`); }
withdraw(amount) { if (this.balance - amount >= BankAccount.overdraftLimit) { this.balance -= amount; console.log(`账户提现:${amount},余额为:${this.balance}`); } }
toString() { return `余额为 ${this.balance}`; }}
BankAccount.overdraftLimit = -100; // 假设可以透支 100
复制代码


接下来创建相应的命令:


const Action = Object.freeze({    deposit: 1,    withdraw: 2,});
class BankAccountCommand { constructor(account, action, amount) { this.account = account; this.action = action; this.amount = amount; }
call() { const callHandler = {}; callHandler[Action.deposit] = (amount) => this.account.deposit(amount); callHandler[Action.withdraw] = (amount) => this.account.withdraw(amount); callHandler[this.action](this.amount); }
undo() { const callHandler = {}; callHandler[Action.deposit] = (amount) => this.account.withdraw(amount); callHandler[Action.withdraw] = (amount) => this.account.deposit(amount); callHandler[this.action](this.amount); }}
// const bankAccount = new BankAccount(100);const cmd = new BankAccountCommand(bankAccount, Action.deposit, 50);cmd.call(); // 账户存入:50,余额为:150
console.log(bankAccount.toString()); // 余额为 150
cmd.undo(); // 账户提现:50,余额为:100console.log(bankAccount.toString()); // 余额为 100
复制代码

15. 迭代器模式

迭代器模式访问对象的元素而不暴露其底层表示。


在面向对象编程中,迭代器模式是一种设计模式,其中迭代器用于遍历容器并访问容器的元素。 —— 维基百科

实例

将举一个数组的例子,在其中打印一个数组的值,然后使用迭代器将其值对调输出。


class Stuff {    constructor() {        this.a = 33;        this.b = 66;    }
[Symbol.iterator]() { let i = 0; return { next: () => { return { done: i > 1, value: this[i++ === 0 ? "a" : "b"], }; }, }; }
get backwards() { let i = 0; return { next: () => { return { done: i > 1, value: this[i++ === 0 ? "b" : "a"], }; }, [Symbol.iterator]: function () { return this; }, }; }}
const values = [100, 200, 300];for (const i in values) { console.log(`索引 ${i} 的值 ${values[i]}`);}
for (const v in values) { console.log(`值为 ${v}`);}
const stuff = new Stuff();console.log("=====>正常打印<======");for (const item of stuff) { console.log(item);}console.log("=====>对调打印<======");for (const item of stuff.backwards) { console.log(item);}
复制代码


运行后在终端显示结果如下:


索引 0 的值 100索引 1 的值 200索引 2 的值 300值为 0值为 1值为 2=====>正常打印<======3366=====>对调打印<======6633
复制代码


发布于: 23 分钟前阅读数: 5
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
ES6 类聊 JavaScript 设计模式之行为型(一)_JavaScript_devpoint_InfoQ写作社区