mcpField
F
flyweight-pattern

flyweight-pattern

github.com/patternsdev开发257612 次安装28 周前更新
代码仓库

关于 flyweight-pattern

一项介绍 JavaScript 享元模式的学习技能,通过复用共享对象状态,减少大量相似对象的内存占用。示例使用 ISBN 缓存书籍数据,并区分共享信息与副本信息。

主要功能

  1. 01复用共享对象实例
  2. 02使用 Map 缓存对象
  3. 03分离共享状态与独有状态
  4. 04跟踪单本书籍副本

适用场景

  1. 01表示同一本书的多个副本
  2. 02减少相似对象的内存占用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patternsdev/skills --skill flyweight-pattern

安装后在 Claude Code 中输入/flyweight-pattern确认已加载。

详细介绍

享元模式

创建大量相似对象时,享元模式有助于节省内存。

在我们的应用中,我们希望用户能够添加书籍。所有书籍都有 title、author 和 isbn 编号!不过,图书馆通常不会只有一本书的一个副本:同一本书通常会有多个副本。

适用场景

  • 创建可能耗尽可用内存的大量对象时
  • 许多对象共享相同的内在属性时(例如,ISBN 相同的书籍)

不适用场景

  • 对象数量较少,内存不是问题时
  • 对象几乎没有共享的内在属性时——区分内在状态和外在状态会增加复杂性,却无法节省内存
  • 额外的查找和管理开销超过内存收益时

说明

  • 将内在(共享)状态与外在(唯一)状态分离
  • 使用 Map 或类似结构缓存并重用共享对象实例
  • 在许多情况下,可以考虑使用 JavaScript 的原型继承作为更简单的替代方案

详情

如果同一本书有多个副本,那么每次都创建一个新的书籍实例并没有太大用处。相反,我们希望创建多个 Book 构造函数实例,让它们代表同一本书。

class Book {
  constructor(title, author, isbn) {
    this.title = title;
    this.author = author;
    this.isbn = isbn;
  }
}

现在来实现向列表中添加新书的功能。如果一本书的 ISBN 编号相同,也就是说属于同一种书,我们就不想创建全新的 Book 实例。相反,我们应该先检查这本书是否已经存在。

const books = new Map();

const createBook = (title, author, isbn) => {
  const existingBook = books.has(isbn);

  if (existingBook) {
    return books.get(isbn);
  }
};

如果其中还没有这本书的 ISBN 编号,我们就创建一本新书,并将其 ISBN 编号添加到 isbnNumbers 集合中。

const createBook = (title, author, isbn) => {
  const existingBook = books.has(isbn);

  if (existingBook) {
    return books.get(isbn);
  }

  const book = new Book(title, author, isbn);
  books.set(isbn, book);

  return book;
};

createBook 函数帮助我们创建同一种书的新实例。不过,图书馆通常会有同一本书的多个副本!现在来创建一个 addBook 函数,以便添加同一本书的多个副本。该函数应调用 createBook 函数,后者会返回新创建的 Book 实例,或返回已经存在的实例。

为了跟踪副本总数,我们创建一个 bookList 数组,用于存放图书馆中的所有书籍。

const bookList = [];

const addBook = (title, author, isbn, availability, sales) => {
  const book = {
    ...createBook(title, author, isbn),
    sales,
    availability,
    isbn,
  };

  bookList.push(book);
  return book;
};

太好了!每次添加一本书的副本时,我们都可以有效地重用该书已有的 Book 实例,而不是创建新的实例。现在为 3 本书创建 5 个副本:Harry Potter、To Kill a Mockingbird 和 The Great Gatsby。

addBook("Harry Potter", "JK Rowling", "AB123", false, 100);
addBook("Harry Potter", "JK Rowling", "AB123", true, 50);
addBook("To Kill a Mockingbird", "Harper Lee", "CD345", true, 10);
addBook("To Kill a Mockingbird", "Harper Lee", "CD345", false, 20);
addBook("The Great Gatsby", "F. Scott Fitzgerald", "EF567", false, 20);

虽然有 5 个副本,但我们只有 3 个 Book 实例!

创建大量可能耗尽所有可用 RAM 的对象时,享元模式很有用。它可以帮助我们尽量减少内存消耗。

在 JavaScript 中,我们可以通过原型继承轻松解决这个问题。如今,硬件通常配有数 GB 的 RAM,因此享元模式的重要性有所降低。

来源

参考资料

评论

支持 Markdown