扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
我先简单地描述一下功能要求,要求设计一种数据结构,支持网格控件(图形化)实现矩形区域的合并效果(Merged)。非矩形区域的合并不在支持范围之内。
大家可能都在使用各种各样的网格控件,最出名的可能是FlexGrid。不过大家可以也思考思考,如果是你的话,你会如何设计呢?
有一个最基本的方法,每一个网格CELL中预置一个变量:MergeID。我们姑且将这种方法称之为"MergeID法"。此方法规则比较简单:没有合并的CELL的MergeID都是0,相邻矩形区域的合并CELLs的MergeID相同,且不为0。将0特殊处理,是为了加快处理速度,毕竟,大多数都是没有合并的CELL。
1 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1
如上面的网格,则左上角六个CELL合并,右下角四个CELL合并。
这种方法的最大问题在于,空间占有比较浪费,特别是对那些从没有合并的CELL。另外,对于合并格的描述不清晰,整个网格中有多少合并格也不能简单获取,必须经过遍历才知道。
针对上面的分析,提出第二种方案,我们称之为"MergeRange List",这种方法的最大优势在于将所有合并的矩形区域统一管理起来,形成一个列表。网格控件在访问Merge属性的时候,再到Range列表中查找,如果找到,则属于合并格,否则为非合并格。
这个方式在FlexGrid就被使用。显然这种方法比较成熟。不过这种方式在管理对象的时候,不容易对应。需要经过映射。这在需要大量访问网格CELL对象的时候,会产生一些效率浪费。
熟悉HTML的人,大概还知道HTML的表示方式,在网格上通过rowspan和colspan来定义。在有合并的CELL的左上角上,定义其向右和向下的合并范围。通过这个范围定义,我们也可以确定合并区域。这种方式的定义简单。不过实现起来,其实有一些问题。
我们上面讨论几种方案的时候,忽略了一个问题,那就是我们一般的网格结构,很可能是一个CELL对应一个对象。那样的话,我们可以有一个新的方案,这个方案和第一个MergeID方案联系在一起,但是我们不需要额外的MergeID属性,而是直接使用Object的对象指针。只需要判断CELL周围的对象是否相等,就可以知道其合并范围。合并区域的所有CELL的对象相同。这样,在取数据的时候,不需要进行额外映射。而在网格控件绘制的时候,才需要合并区域查找。效率应该可以满足。我们就将这种方法叫"Ojbect/MergeID"吧。
总结列举一下四种方法:
这四种方法各有利弊。其实在我们设计过程中,应该抓住一个基本点,要的是空间还是效率,还是两者都要。不同的要求,使用不同的设计。
婵犵數濮烽。浠嬪焵椤掆偓閸熷潡鍩€椤掆偓缂嶅﹪骞冨Ο璇茬窞闁归偊鍓涢悾娲⒑闂堟单鍫ュ疾濠婂嫭鍙忔繝濠傜墛閸嬨劍銇勯弽銊с€掗柟钘夊暣閺岀喖鎮滈埡鍌涚彋閻庤娲樺畝绋跨暦閸洖鐓涢柛灞剧矋濞堟悂姊绘担绛嬪殐闁搞劋鍗冲畷銏ゅ冀椤愩儱小闂佹寧绋戠€氼參宕伴崱妯镐簻闁靛牆鎳庢慨顒€鈹戦埥鍡椾簼婵犮垺锚铻炴俊銈呮噺閸嬪倹绻涢崱妯诲碍閻庢艾顦甸弻宥堫檨闁告挾鍠庨锝夘敆娓氬﹦鐭楁繛鎾村焹閸嬫捇鏌e☉娆愬磳闁哄本绋戦埞鎴﹀川椤曞懏鈻婄紓鍌欑劍椤ㄥ懘鎯岄崒鐐靛祦閹兼番鍔岄悞鍨亜閹烘垵顏╅悗姘槹閵囧嫰寮介妸褎鍣ョ紓浣筋嚙濡繈寮婚悢纰辨晣鐟滃秹鎮橀懠顒傜<閺夊牄鍔庣粻鐐烘煛鐏炶姤鍠橀柡浣瑰姍瀹曠喖顢橀悩铏钒闂備浇宕垫慨鎶芥⒔瀹ュ鍨傞柦妯猴級閿濆绀嬫い鏍ㄧ☉濞堟粓姊虹涵鍛【妞ゎ偅娲熼崺鈧い鎺嗗亾闁挎洩濡囧Σ鎰板籍閸繄顓洪梺缁樺姇瀵剙螖閸涱喚鍘搁梺鍓插亽閸嬪嫰鎮橀敃鍌涚厱閻庯綆鍋嗘晶顒傜磼閸屾稑绗ч柟鐟板閹煎湱鎲撮崟闈涙櫏闂傚倷绀侀幖顐も偓姘卞厴瀹曞綊鏌嗗鍛紱閻庡箍鍎遍ˇ浼村磿瀹ュ鐓曢柡鍥ュ妼婢ь垰霉閻樿秮顏堟箒闂佹寧绻傚Λ妤呭煝閺囥垺鐓冪憸婊堝礈濮樿泛钃熼柕濞у嫷鍋ㄩ梺缁樺姇椤曨參鍩㈤弴銏″€甸柨婵嗗€瑰▍鍥ㄣ亜韫囨稐鎲鹃柡灞炬礋瀹曢亶顢橀悢濂変紦