优化小技巧——复杂属性对象的read模式

本帖最后由 Aone 于 2013-7-27 12:23 编辑

想必Rectangle或者Point这样的数据类在我们的程序中特别是当前的游戏中是非常常用的类型。那么一些类中获取这些属性的时候为了封装,往往会写一个get函数return一个复制的Rectangle对象给外部。目的是为了防止被获取内部rect引用后直接被修改。
比如:
  1. public function get bodyRect():Rectangle{
  2.         return _bodyRect.clone();
  3. }
  4. private var _bodyRect:Rectangle = new Rectangle;
复制代码
但是每次都clone()也就是每次重新new一个也会比较消耗性能,同时会产生大量的临时对象(也占点内存)。在一些密集计算的地方一次循环可能就会需要大量的使用类似的属性,也就是说会产生大量此类临时对象,而运算过后也都是直接丢弃。着实有点浪费。

于是我想到用一个read模式。比如针对上面例子中get bodyRect()声明一个 readBodyRect(_rect:Rectangle)方法,过程中不再产生新的Rectangle对象,而是接收一个Rectangle来修改其值。
  1. public function readBodyRect(_rect:Rectangle):void{
  2. _rect.x = _bodyRect.x;
  3. _rect.y = _bodyRect.y;
  4. _rect.width = _bodyRect.width;
  5. _rect.height = _bodyRect.height;
  6. }
  7. private var _bodyRect:Rectangle = new Rectangle;
复制代码
这样在一些密集计算的地方只要在循环外建立一个临时的Rectangle对象专门用来被重复修改即可。即提高了性能又保持了封装性。
那么大概能为我们节省多少性能呢?可以跑一下下面的测试程序
  1. import flash.geom.Rectangle;
  2. function getRectangle():Rectangle{
  3.         return _rect.clone();
  4. }
  5. function readRectangle(_rect:Rectangle):void{
  6.         _rect.x = 100;
  7.         _rect.y = 100;
  8.         _rect.width = 100;
  9.         _rect.height = 100;
  10. }
  11. var _rect:Rectangle = new Rectangle;
  12. var _old:int = getTimer();
  13. for(var i:int = 0; i < 1000000; i += 1){
  14.         getRectangle();
  15. }
  16. trace("正常模式:",getTimer() - _old);
  17. _old = getTimer();
  18. for(i = 0; i < 1000000; i += 1){
  19.         readRectangle(_rect);
  20. }
  21. trace("read模式:",getTimer() - _old);
复制代码
最后,以上只是用Rectangle举的例子,在实际项目中可以使用地方还是比较多的,实际只要是需要密集计算频繁get的地方都可以使用。
原文地址:https://www.cnblogs.com/chenhongyu/p/3290618.html