JavaScript デザイン パターンを学ぶ - flyweight pattern_javascript スキル

WBOY
リリース: 2016-05-16 15:19:27
オリジナル
1022 人が閲覧しました

1. 定義

フライウェイト モードは、パフォーマンスの最適化に使用されるモードです。その中心となるのは、共有テクノロジを使用して、多数の細かいスケールのオブジェクトを効果的にサポートすることです。
JavaScriptでは、ブラウザ、特にモバイルブラウザはメモリをあまり割り当てないため、メモリをいかに節約するかが非常に重要になります。
フライウェイト モードは、時間をスペースと交換する最適化モードです

  • 下着工場には男性用の下着が100種類、女性用の下着が100種類あり、それぞれの下着の写真を撮る必要があります。フライ級モデルを使用しない場合は 200 個のプラモデルが必要ですが、フライ級モデルを使用する場合は男性と女性のモデルが 1 つずつ必要になります。

2. フライウェイト モードはどのようなシナリオで使用されますか?

(1) プログラム内で同様のオブジェクトが多数使用されており、メモリのオーバーヘッドが大きくなります
(2) オブジェクトのほとんどの状態は外部状態に変更でき、外部状態を取り除いた後、多数のオブジェクトを比較的少数の共有オブジェクトに置き換えることができます

3. フライウェイトモードを適用するにはどうすればよいですか?

最初のレイヤーは、主にメモリ内の多数の同様のオブジェクトに適用されます。 2 つ目は DOM レイヤーで適用され、中央イベント マネージャーで Flyweight を使用して、親コンテナーの各子要素にイベント ハンドラーをアタッチすることを回避できます。

Flyweight パターンでは、オブジェクトのプロパティを

内部状態外部状態 に分割する必要があります。 内部状態は特定のシーンから独立しており、通常は変化せず、一部のオブジェクトによって共有される可能性があります。 外部状態は特定のシナリオに依存し、シナリオに基づく変更は共有できません。

ファクトリー モードは、フライウェイト モードでよく使用されます。フライウェイト ファクトリーは、内部状態オブジェクトを保存するためにフライウェイト プール (パターン プール) を維持する役割を果たします。

欠点: オブジェクトの数が少ない場合、システムのオーバーヘッドが増加し、実装がより複雑になる可能性があります。

4. 例: ファイルのアップロード

var Upload = function(uploadType) {
  this.uploadType = uploadType;
}

/* 删除文件(内部状态) */
Upload.prototype.delFile = function(id) {
  uploadManger.setExternalState(id, this);  // 把当前id对应的外部状态都组装到共享对象中
  // 大于3000k提示
  if(this.fileSize < 3000) {
    return this.dom.parentNode.removeChild(this.dom);
  }
  if(window.confirm("确定要删除文件吗?" + this.fileName)) {
    return this.dom.parentNode.removeChild(this.dom);
  }
}

/** 工厂对象实例化 
 * 如果某种内部状态的共享对象已经被创建过,那么直接返回这个对象
 * 否则,创建一个新的对象
 */
var UploadFactory = (function() {
  var createdFlyWeightObjs = {};
  return {
    create: function(uploadType) {
      if(createdFlyWeightObjs[uploadType]) {
        return createdFlyWeightObjs[uploadType];
      }
      return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
    }
  };
})();

/* 管理器封装外部状态 */
var uploadManger = (function() {
  var uploadDatabase = {};

  return {
    add: function(id, uploadType, fileName, fileSize) {
      var flyWeightObj = UploadFactory.create(uploadType);
      var dom = document.createElement('div');
      dom.innerHTML = "<span>文件名称:" + fileName + ",文件大小:" + fileSize +"</span>"
             + "<button class='delFile'>删除</button>";

      dom.querySelector(".delFile").onclick = function() {
        flyWeightObj.delFile(id);
      };
      document.body.appendChild(dom);

      uploadDatabase[id] = {
        fileName: fileName,
        fileSize: fileSize,
        dom: dom
      };

      return flyWeightObj;
    },
    setExternalState: function(id, flyWeightObj) {
      var uploadData = uploadDatabase[id];
      for(var i in uploadData) {
        // 直接改变形参(新思路!!)
        flyWeightObj[i] = uploadData[i];
      }
    }
  };
})();

/*触发上传动作*/
var id = 0;
window.startUpload = function(uploadType, files) {
  for(var i=0,file; file = files[i++];) {
    var uploadObj = uploadManger.add(++id, uploadType, file.fileName, file.fileSize);
  }
};

/* 测试 */
startUpload("plugin", [
  {
    fileName: '1.txt',
    fileSize: 1000
  },{
    fileName: '2.txt',
    fileSize: 3000
  },{
    fileName: '3.txt',
    fileSize: 5000
  }
]);
startUpload("flash", [
  {
    fileName: '4.txt',
    fileSize: 1000
  },{
    fileName: '5.txt',
    fileSize: 3000
  },{
    fileName: '6.txt',
    fileSize: 5000
  }
]);

ログイン後にコピー
5.補足

(1) 仮パラメータを直接変更する Demo

function f1() {
  var obj = {a: 1};
  f2(obj);
  console.log(obj);  // {a: 1, b: 2}
}
function f2(obj) {
  obj.b = 2;
}
f1();  
ログイン後にコピー

(2) オブジェクト プール、 もパフォーマンス最適化ソリューションです。フライウェイト モードといくつかの類似点がありますが、内部状態と外部状態を分離するプロセスはありません。

var objectPoolFactory = function(createObjFn) {
  var objectPool = [];
  return {
    create: function() {
      var obj = objectPool.lenght === 0 &#63; createObjFn.apply(this, arguments) : objectPool.shift();
      return obj;
    },
    recover: function() {
      objectPool.push(obj);
    }
  };
}
ログイン後にコピー
この記事が JavaScript プログラミングを学習するすべての人に役立つことを願っています。
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート