`

Ext中的享元模式(flyweight)

    博客分类:
  • Ext
阅读更多

今天看Ext的sample,不明白下面一段话:

  Ext.fly(node.ui.elNode).ghost('l', {
                callback: node.remove, scope: node, duration: .4
            });

 主要是对Ext.fly不甚明了,于是搜了一把,发现收获还不小,与大家共享之。

Ext.fly是Ext.Element.flyweight的简写,是Ext的Element类中对享元模式的应用,因Element类中的方法都是对DOM对象的操作,而DOM操作又是Ext的核心,所以如果太过于频繁的创建DOM节点的话会造成性能的下降,因而采用享元模式,享元模式以共享的方式高效地支持大量的细粒度对象,有关享元模式的详细资料,可以参见http://fengzl.iteye.com/blog/117129的blog。

在Ext的wiki中对Flyweight有一个简短的介绍,即‘Use sharing to support large numbers of fine-grained objects efficiently.  ’,有个哥们不懂,到论坛上发问,下面就是Ext的核心developer的回答:

 

Ext.Element wraps a lot of functionality around DOM element/node, for example functions like hide, show, all animation stuff, dimensions getting and setting function and a lot more.

Ext.Element keeps reference to DOM element it is wrapped around in dom property. Once you have an Ext.Element (e.g. you call Ext.get('some-id') it is an instance of Element class and you can work with it as such.

Now, imagine that you need to hide 1000 DOM nodes, you call 1000 times Ext.get('some-one-of-1000-id').hide() so you create 1000 instances of Element just to call one function: hide.

Ext.fly is one instance of Ext.Element with "replaceable" DOM node it is wrapped around. If you call 1000 times Ext.fly('some-one-of-1000-id').hide() you 1000 times replace dom property of one instance of Ext.Element.

Result: higher performance, lower memory usage.

You only need to keep in mind that you cannot keep Element returned by Ext.fly for later use as it's dom will sooner or later gets replaced by another one.

 

下面我们来看一下其实现(Ext.Element):


Ext.fly = El.fly;
/**
 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
 * the dom node can be overwritten by other code.
 * @param {String/HTMLElement} el The dom node or id
 * @param {String} named (optional) Allows for creation of named reusable flyweights to
 *                                  prevent conflicts (e.g. internally Ext uses "_internal")
 * @static
 * @return {Element} The shared Element object (or null if no matching element was found)
 */
El.fly = function(el, named){
    named = named || '_global';
    el = Ext.getDom(el);
    if(!el){
        return null;
    }
    if(!El._flyweights[named]){
        El._flyweights[named] = new El.Flyweight();
    }
    El._flyweights[named].dom = el;
    return El._flyweights[named];
};
那么EI._flyweight又是什么呢? 
El._flyweights = {};
var flyFn = function(){};
flyFn.prototype = El.prototype;
var _cls = new flyFn();

// dom is optional
El.Flyweight = function(dom){
    this.dom = dom;
};

El.Flyweight.prototype = _cls;
El.Flyweight.prototype.isFlyweight = true;
这样,基本上明白什么是Ext.fly了吧?同时,也应该明白Ext.fly和Ext.get的区别了吧?

 

 

分享到:
评论
8 楼 li6151770 2009-02-03  
本来还有点理解fly,现在看你们的回答现在彻底不知道什么意思了。。。。。
7 楼 jateide 2008-09-24  
jljlpch 写道
jianfeng008cn 写道
equalto 写道
幸亏我本来明白,要不真的搞不明白了 ^_^

Element,不是来创建DOM的,这两个概念完全不同,DOM是浏览器自己的,Element是Ext的对象.
Element对象里面,有个属性dom,指向了实际存在于浏览器对象树里面的DOM元素,Ext用Element做中介,操作dom作很多操作,这里屏蔽了浏览器差异(起码这个是它的一个目标),也集成了许多的便利的函数,比如说getSize setSize child.

可以说,Element,就是Ext里面操作web元素的一个基本接口.

但是,有个问题是,每个Element都要和dom对应,也就是说,你如果要操作多少个web元素,就要有多少个Element对象实例.
那肯定是不行的.
flyweight,轻量级Element元素应运而生,它使得多个dom元素共享一个Flyweight对象(它完全继承了Element的方法),每次使用,都临时的修改dom属性,指向当前的web元素对象.
这样就节省了创建Element的开销.


个人理解,一家之言哈.



其实用静态方法可以避免这个问题,我感觉ext有点滥用享元模式,element中包含享元模式是合理的,但是在ext-lib等地方也调用这个方法就显得有点不地道了,只有对整个dom操作的逻辑了然于胸才明白这样调用产生的相互依赖不会造成冲突。


非常赞同。觉得有点滥用设计模式。

满瓶不晃,半瓶晃荡。自以为是
6 楼 jljlpch 2008-09-12  
jianfeng008cn 写道
equalto 写道
幸亏我本来明白,要不真的搞不明白了 ^_^

Element,不是来创建DOM的,这两个概念完全不同,DOM是浏览器自己的,Element是Ext的对象.
Element对象里面,有个属性dom,指向了实际存在于浏览器对象树里面的DOM元素,Ext用Element做中介,操作dom作很多操作,这里屏蔽了浏览器差异(起码这个是它的一个目标),也集成了许多的便利的函数,比如说getSize setSize child.

可以说,Element,就是Ext里面操作web元素的一个基本接口.

但是,有个问题是,每个Element都要和dom对应,也就是说,你如果要操作多少个web元素,就要有多少个Element对象实例.
那肯定是不行的.
flyweight,轻量级Element元素应运而生,它使得多个dom元素共享一个Flyweight对象(它完全继承了Element的方法),每次使用,都临时的修改dom属性,指向当前的web元素对象.
这样就节省了创建Element的开销.


个人理解,一家之言哈.



其实用静态方法可以避免这个问题,我感觉ext有点滥用享元模式,element中包含享元模式是合理的,但是在ext-lib等地方也调用这个方法就显得有点不地道了,只有对整个dom操作的逻辑了然于胸才明白这样调用产生的相互依赖不会造成冲突。


非常赞同。觉得有点滥用设计模式。
5 楼 equalto 2008-09-12  
jianfeng008cn 写道


其实用静态方法可以避免这个问题,我感觉ext有点滥用享元模式,element中包含享元模式是合理的,但是在ext-lib等地方也调用这个方法就显得有点不地道了,只有对整个dom操作的逻辑了然于胸才明白这样调用产生的相互依赖不会造成冲突。


能把代码看到lib,是很不错了,但是,再多看多想,你就会发现,没什么不地道的。
Ext自己的代码中,使用了flyweight的地方,我看不出来有什么大不了,Ext.fly函数的第二个参数name,已经可以说明作者的意图了,如果乱用一气,引起错误,那能怎么说呢?
——只能说做出这个事情的人傻。
我在用fly的时候,个别地方需要特别指定name,都用公司的简称作前缀。

btw,最后一句话,我很不明白,Element在我看来,是Ext对于页面元素的一个包装类,就是避免一些dom操作的麻烦。怎么又说那些的话。
4 楼 jianfeng008cn 2008-09-10  
equalto 写道
幸亏我本来明白,要不真的搞不明白了 ^_^

Element,不是来创建DOM的,这两个概念完全不同,DOM是浏览器自己的,Element是Ext的对象.
Element对象里面,有个属性dom,指向了实际存在于浏览器对象树里面的DOM元素,Ext用Element做中介,操作dom作很多操作,这里屏蔽了浏览器差异(起码这个是它的一个目标),也集成了许多的便利的函数,比如说getSize setSize child.

可以说,Element,就是Ext里面操作web元素的一个基本接口.

但是,有个问题是,每个Element都要和dom对应,也就是说,你如果要操作多少个web元素,就要有多少个Element对象实例.
那肯定是不行的.
flyweight,轻量级Element元素应运而生,它使得多个dom元素共享一个Flyweight对象(它完全继承了Element的方法),每次使用,都临时的修改dom属性,指向当前的web元素对象.
这样就节省了创建Element的开销.


个人理解,一家之言哈.



其实用静态方法可以避免这个问题,我感觉ext有点滥用享元模式,element中包含享元模式是合理的,但是在ext-lib等地方也调用这个方法就显得有点不地道了,只有对整个dom操作的逻辑了然于胸才明白这样调用产生的相互依赖不会造成冲突。
3 楼 KKFC 2008-07-29  
ext里面还有不少design pattern的东东的 -这是它比其他js lib来得精彩的地方之一

引用

设计模式和 Ext JS
开发人员应该会喜欢 Ext JS 经过深思熟虑的设计和实现。它的面向对象设计模式反映了对象之间的关系和交互。据设计者说,开发 Ext JS 时使用的设计模式在很大程度上受到 Head First Design Patterns 这本书(Eric Freeman 等著,参见 参考资料)的影响。查看 Ext JS 源代码,就会发现创建模式(包括 singleton 设计模式)、结构模式(包括 flyweight 设计模式)和行为模式(包括 observer 模式)。


IBM developerWorks 中国  >  Web development  > 用 Ext JS 构建 Ajax 应用程序
2 楼 hintcnuie 2008-07-28  
有点不太同意,主要集中于对DOM和BOM的理解上。一个html页面,就会产生一个DOM树,浏览器会负责实现这个DOM树,但不能说这个DOM就变成浏览器自己的了,只能说是浏览器负责维护这个DOM的实例。
1 楼 equalto 2008-07-22  
幸亏我本来明白,要不真的搞不明白了 ^_^

Element,不是来创建DOM的,这两个概念完全不同,DOM是浏览器自己的,Element是Ext的对象.
Element对象里面,有个属性dom,指向了实际存在于浏览器对象树里面的DOM元素,Ext用Element做中介,操作dom作很多操作,这里屏蔽了浏览器差异(起码这个是它的一个目标),也集成了许多的便利的函数,比如说getSize setSize child.

可以说,Element,就是Ext里面操作web元素的一个基本接口.

但是,有个问题是,每个Element都要和dom对应,也就是说,你如果要操作多少个web元素,就要有多少个Element对象实例.
那肯定是不行的.
flyweight,轻量级Element元素应运而生,它使得多个dom元素共享一个Flyweight对象(它完全继承了Element的方法),每次使用,都临时的修改dom属性,指向当前的web元素对象.
这样就节省了创建Element的开销.


个人理解,一家之言哈.

相关推荐

Global site tag (gtag.js) - Google Analytics