前端设计模式学习系列文章-享元模式

88 阅读3分钟

当我们创建大量相似的对象时,享元模式是节省内存的一种有用方法。

在我们的应用程序中,我们希望用户能够添加书籍。所有书籍都有一个title、一个author和一个isbn编号!然而,图书馆通常不仅仅拥有一本书的一本:它通常拥有同一本书的多本。

如果同一本书有多个副本,那么每次创建一个新的书籍实例并不是很有用。相反,我们想要创建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我们可以有效地使用Book该特定副本的现有实例,而不是每次添加副本时创建一个新实例。让我们创建 3 本书的 5 个副本:《哈利·波特》、《杀死一只知更鸟》和《了不起的盖茨比》。

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实例!

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

const isbnNumbers = new Set();
const bookList = [];

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

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

const createBook = (title, author, isbn) => {
  const book = isbnNumbers.has(isbn);
  if (book) {
    return book;
  } else {
    const book = new Book(title, author, isbn);
    isbnNumbers.add(isbn);
    return book;
  }
};

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);

console.log("Total amount of copies: ", bookList.length);
console.log("Total amount of books: ", isbnNumbers.size);
Open CodeSandbox

当您创建大量对象时,享元模式非常有用,这可能会耗尽所有可用 RAM。它允许我们最大限度地减少消耗的内存量。

在JavaScript中,我们可以通过原型继承轻松解决这个问题。如今,硬件拥有 GB 的 RAM,这使得享元模式不再那么重要。