享元模式最适合于解决因创建大量类似对象而累及性能的问题,本文将来总结JavaScript设计模式编程中的享元模式使用,包括在DOM操作时的利用示例:
享元模式不同于一般的设计模式,它主要用来优化程序的性能,它最适合解决大量类似的对象而产生的性能问题。享元模式通过分析应用程序的对象,将其解析为内在数据和外在数据,减少对象的数量,从而提高应用程序的性能。
基本知识
享元模式通过共享大量的细粒度的对象,减少对象的数量,从而减少对象的内存,提高应用程序的性能。其基本思想就是分解现有类似对象的组成,将其展开为可以共享的内在数据和不可共享的外在数据,我们称内在数据的对象为享元对象。通常还需要一个工厂类来维护内在数据。
在JS中,享元模式主要有下面几个角色组成:
(1)客户端:用来调用享元工厂来获取内在数据的类,通常是应用程序所需的对象,
(2)享元工厂:用来维护享元数据的类
(3)享元类:保持内在数据的类
享元模式的实现和应用
一般实现
我们举个例子进行说明:苹果公司批量生产iphone,iphone的大部分数据比如型号,屏幕都是一样,少数部分数据比如内存有分16G,32G等。未使用享元模式前,我们写代码如下:
function Iphone(model, screen, memory, SN) { this. model = model; this.screen = screen; this.memory = memory; this.SN = SN; } var phones = []; for (var i = 0; i < 1000000; i++) { var memory = i % 2 == 0 ? 16 : 32; phones.push(new Iphone("iphone6s", 5.0, memory, i)); }
这段代码中,创建了一百万个iphone,每个iphone都独立申请一个内存。但是我们仔细观察可以看到,大部分iphone都是类似的,只是内存和序列号不一样,如果是一个对性能要求比较高的程序,我们就要考虑去优化它。
大量相似对象的程序,我们就可以考虑用享元模式去优化它,我们分析出大部分的iphone的型号,屏幕,内存都是一样的,那这部分数据就可以公用,就是享元模式中的内在数据,定义享元类如下:
function IphoneFlyweight(model, screen, memory) { this.model = model; this.screen = screen; this.memory = memory; }
我们定义了iphone的享元类,其中包含型号,屏幕和内存三个数据。我们还需要一个享元工厂来维护这些数据:
var flyweightFactory = (function () { var iphones = {}; return { get: function (model, screen, memory) { var key = model + screen + memory; if (!iphones[key]) { iphones[key] = new IphoneFlyweight(model, screen, memory); } return iphones[key]; } }; })();
在这个工厂中,我们定义了一个字典来保存享元对象,提供一个方法根据参数来获取享元对象,如果字典中有则直接返回,没有则创建一个返回。
接着我们创建一个客户端类,这个客户端类就是修改自iphone类:
function Iphone(model, screen, memory, SN) { this.flyweight = flyweightFactory.get(model, screen, memory); this.SN = SN; }
然后我们依旧像之间那样生成多个iphone
var phones = []; for (var i = 0; i < 1000000; i++) { var memory = i % 2 == 0 ? 16 : 32; phones.push(new Iphone("iphone6s", 5.0, memory, i)); } console.log(phones);
这里的关键就在于Iphone构造函数里面的this.flyweight = flyweightFactory.get(model, screen, memory)。这句代码通过享元工厂去获取享元数据,而在享元工厂里面,如果已经存在相同数据的对象则会直接返回对象,多个iphone对象共享这部分相同的数据,所以原本类似的数据已经大大减少,减少的内存的占用。
享元模式在DOM中的应用
享元模式的一个典型应用就是DOM事件操作,DOM事件机制分成事件冒泡和事件捕获。我们简单介绍一下这两者:
事件冒泡:绑定的事件从最里层的元素开始触发,然后冒泡到最外层
事件捕获:绑定的事件从最外层的元素开始触发,然后传到最里层
假设我们HTML中有一个菜单列表
<ul class="menu"> <li class="item">选项1</li> <li class="item">选项2</li> <li class="item">选项3</li> <li class="item">选项4</li> <li class="item">选项5</li> <li class="item">选项6</li> </ul>
点击菜单项,进行相应的操作,我们通过jQuery来绑定事件,一般会这么做:
$(".item").on("click", function () { console.log($(this).text()); })
给每个列表项绑定事件,点击输出相应的文本。这样看暂时没有什么问题,但是如果是一个很长的列表,尤其是在移动端特别长的列表时,就会有性能问题,因为每个项都绑定了事件,都占用了内存。但是这些事件处理程序其实都是很类似的,我们就要对其优化。
$(".menu").on("click", ".item", function () { console.log($(this).text()); })
通过这种方式进行事件绑定,可以减少事件处理程序的数量,这种方式叫做事件委托,也是运用了享元模式的原理。事件处理程序是公用的内在部分,每个菜单项各自的文本就是外在部分。我们简单说下事件委托的原理:点击菜单项,事件会从li元素冒泡到ul元素,我们绑定事件到ul上,实际上就绑定了一个事件,然后通过事件参数event里面的target来判断点击的具体是哪一个元素,比如低级第一个li元素,event.target就是li,这样就能拿到具体的点击元素了,就可以根据不同元素进行不同的处理。
总结
享元模式是一种优化程序性能的手段,通过共享公用数据来减少对象数量以达到优化程序的手段。享元模式适用于拥有大量类似对象并且对性能有要求的场景。因为享元模式需要分离内部和外部数据,增加了程序的逻辑复杂性,建议对性能有要求的时候才使用享元模式。
享元模式之利:
可以把网页的资源符合降低几个数量级。即使享元模式的应用无法将实例的个数削减到一个,你仍能够从中获益不少。
这种节省不需要大量修改原有代码。在创建了管理器、工厂和享元之后,就需要对代码进行的修改只不过是从直接实例化目标类改为调用管理器对象的某个方法。
享元模式之弊:
如果把它用在不必要的地方,其结果反而有损代码的运行效率。这种模式在优化代码的同时,也提高了其复杂程度,这会给调试和维护造成困难。
它之所以会妨碍调试,是因为现在可能出错的地方变成了三个:管理器、工厂和享元。
这种优化也会使维护变得更加困难。现在你面对的不是由封装着数据的对象构成的清晰架构,而是一堆又碎又乱的东西。其中的数据至少分两处保存。最好注释标明内在数据和外在数据。
只有在必要的时候才应该进行这种优化。必须在运行效率和可维护性之间进行权衡。如果拿不准是否需要使用享元模式,那么你很可能并不需要它。享元模式适合的是系统资源已经用得差不多而且明显需要进行某种优化这样一类场合。
这种模式对Javascript程序员特别有用,因为它可以用来减少网页上所要使用的DOM元素的数量,要知道这些元素需要耗费许多内存。结合使用这种模式与组合模式等组织型可以开发出功能丰富的复杂Web应用系统,它们可以平稳的运行在任何现代Javascript环境中。
享元模式的适用场合:
网页中必须使用了大量资源密集型对象。如果只会用到少许这类对象,这种优化并不划算。
对象中所保存的数据至少有一部分能被转化为外在数据。此外,将这些数据存储在对象外部所占用的资源应该相对较少,否则这种做法对于性能的提示实际上毫无意义。那种大量包含基础性代码和HTML内容的对象可能比较适合这种优化。
将外在数据分离出去后,独一无二的对象的数目相对较少。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
对javascript Function函数深入理解与实战(附上代码)
以上是详细解读在JavaScript设计模式编程中的享元模式的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver Mac版
视觉化网页开发工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能