Js设计模式(结构型)之七--亨元模式
Flyweight 亨元模式
1、亨元模式
享元模式是一个优化重复、缓慢和低效数据共享代码的经典结构化解决方案。它的目标是以相关对象尽可能多的共享数据,来减少应用程序中内存的使用(例如:应用程序的配置、状态等)。
2、亨元模式使用方法
a) 数据层
数据层,基于存储在内存中的大量相同对象的数据共享的概念。亨元模式大部分时候被应用于数据层。
亨元模式的实例:
实现一个管理一个图书馆中所有书籍的系统。
每一本书的重要元数据:
- ID
- 标题
- 作者
- 类型
- 总页数
- 出版商ID
- ISBN
将需要下面一些属性,来跟踪哪一个成员是被借出的一本特定的书,借出它们的日期,还有预计的归还日期。
- 借出日期
- 借出的成员
- 规定归还时间
- 可借性
var Book = function( id, title, author, genre, pageCount,publisherID, ISBN, checkoutDate, checkoutMember, dueReturnDate,availability ){ this.id = id; this.title = title; this.author = author; this.genre = genre; this.pageCount = pageCount; this.publisherID = publisherID; this.ISBN = ISBN; this.checkoutDate = checkoutDate; this.checkoutMember = checkoutMember; this.dueReturnDate = dueReturnDate; this.availability = availability; }; Book.prototype = { getTitle: function () { return this.title; }, getAuthor: function () { return this.author; }, getISBN: function (){ return this.ISBN; }, // 更新是否借出的状态 updateCheckoutStatus: function( bookID, newStatus, checkoutDate , checkoutMember, newReturnDate ){ this.id = bookID; this.availability = newStatus; this.checkoutDate = checkoutDate; this.checkoutMember = checkoutMember; this.dueReturnDate = newReturnDate; }, // 延长借出期限 extendCheckoutPeriod: function( bookID, newReturnDate ){ this.id = bookID; this.dueReturnDate = newReturnDate; }, // 是否逾期,返回true/false isPastDue: function(bookID){ var currentDate = new Date(); return currentDate.getTime() > Date.parse( this.dueReturnDate ); } };
以上实例对于小规模的藏书可能工作得还好,然而当图书馆扩充至每一本书的多个版本和可用的备份,这样一个大型的库存,我们会发现管理系统的运行随着时间的推移会越来越慢。使用成千上万的书籍对象可能会压倒内存,而我们可以通过享元模式的提升来优化我们的系统:
下面的书籍元数据组合的单一实体将在所有带有一个特定标题的书籍拷贝中共享:
// 亨元模式优化版本 var Book = function ( title, author, genre, pageCount, publisherID, ISBN ) { this.title = title; this.author = author; this.genre = genre; this.pageCount = pageCount; this.publisherID = publisherID; this.ISBN = ISBN; };
外在状态已经被移除了。从图书馆借出所要做的一切都被转移到一个管理器中,由于对象数据现在是分段的,工厂可以被用来做实例化。
现在让我们定义一个非常基本的工厂。我们用它做的工作是,执行一个检查来看看一本给定标题的书是不是之前已经在系统内创建过了;如果创建过了,我们就返回它 - 如果没有,一本新书就会被创建并保存,使得以后可以访问它。这确保了为每一条本质上唯一的数据,我们只创建了一份单一的拷贝:
// 图书工厂 var BookFactory = (function () { var existingBooks = { }, existingBook; return { createBook: function ( title, author, genre, pageCount, publisherID, ISBN ) { // 检查以前是否创建过特定的图书元数据组合 // 或者强制返回一个布尔值 existingBook = existingBooks[ISBN]; if ( !!existingBook ) { // 如果存在,直接返回 return existingBook; } else { // 如果没有,让我们创建图书的新实例并存储它 var book = new Book( title, author, genre, pageCount, publisherID, ISBN ); existingBooks[ISBN] = book; return book; } } }; });
将那些从Book对象中移除的状态存储到图书记录管理器中:
var BookRecordManager = (function () { // 图书记录数据库 var bookRecordDatabase = {}; return { // 在图书馆系统中添加一本新书 addBookRecord: function ( id, title, author, genre, pageCount, publisherID, ISBN, checkoutDate, checkoutMember, dueReturnDate, availability ) { var book = bookFactory.createBook( title, author, genre, pageCount, publisherID, ISBN ); bookRecordDatabase[id] = { checkoutMember: checkoutMember, checkoutDate: checkoutDate, dueReturnDate: dueReturnDate, availability: availability, book: book }; }, // 更新借出的状态 updateCheckoutStatus: function ( bookID, newStatus, checkoutDate, checkoutMember, newReturnDate ) { var record = bookRecordDatabase[bookID]; record.availability = newStatus; record.checkoutDate = checkoutDate; record.checkoutMember = checkoutMember; record.dueReturnDate = newReturnDate; }, // 延长借出期限 extendCheckoutPeriod: function ( bookID, newReturnDate ) { bookRecordDatabase[bookID].dueReturnDate = newReturnDate; }, // 是否逾期 isPastDue: function ( bookID ) { var currentDate = new Date(); return currentDate.getTime() > Date.parse( bookRecordDatabase[bookID].dueReturnDate ); } }; });
这些改变的结果是所有从Book类中提取的数据,现在被存储到了BookManager单例(BookDatabase)的一个属性之中——与我们以前使用大量对象相比可以被认为是更加高效的东西。同书籍借出相关的方法也被设置在这里,因为它们处理的数据是外在的而不内在的。
这个过程确实给我们最终的解决方法增加了一点点复杂性,然而同已经明智解决的数据性能问题相比,这只是一个小担忧,如果我们有同一本书的30份拷贝,现在我们只需要存储它一次就够了。每一个函数也会占用内存。使用享元模式这些函数只在一个地方存在(就是在管理器上),并且不是在每一个对象上面,这节约了内存上的使用。
b) DOM层
DOM层,享元模式被作为事件管理中心,以避免将事件处理程序关联到我们需要相同行为父容器的所有子节点上。
原文地址:https://www.cnblogs.com/doublewhy317/p/12088289.html
- hbase 学习(十二)非mapreduce生成Hfile,然后导入hbase当中
- RavenDb学习(六)查询补充特性
- hbase源码系列(一)Balancer 负载均衡
- OpenCV在车道线查找中的使用
- hbase源码系列(十五)终结篇&Scan续集-->如何查询出来下一个KeyValue
- mac系统下安装、启动、停止mongodb
- 100个Numpy练习【1】
- 100个Numpy练习【2】
- 100个Numpy练习【3】
- 100个Numpy练习【4】
- 100个Numpy练习【5】
- 小窗播放视频的原理和实现(下)
- web实时长图实践
- Android Native 开发之 NewString 与 NewStringUtf 解析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 字符流---输入输出与复制文本文件
- Spring 中的几个 PostProcessor 的区别与联系
- Spring 中基于注解的事务控制及原理分析
- Spring 中根据环境切换配置 @Profile
- Spring 中的属性赋值
- Spring 中控制 Bean 生命周期的几种方式及 BeanPostProcessor 执行原理
- Spring 中的 @Import 注解及向容器中添加 Bean 的几种方式
- Spring 注解开发之 @Conditional
- JDBC 技术应用实践:网上书城后台管理系统
- 思科模拟器:路由器基本配置
- 思科模拟器:实验五——高级路由实验
- 从零开始重新认识 SpringMVC
- 字节跳动Android实习面试凉凉经,两轮面试我被完虐了...
- 高效、简单、方便管理与维护的开源运维工单系统
- python数据库入门编程。