1. 定義
フライウェイト モードは、パフォーマンスの最適化に使用されるモードです。その中心となるのは、共有テクノロジを使用して、多数の細かいスケールのオブジェクトを効果的にサポートすることです。
JavaScriptでは、ブラウザ、特にモバイルブラウザはメモリをあまり割り当てないため、メモリをいかに節約するかが非常に重要になります。
フライウェイト モードは、時間をスペースと交換する最適化モードです
2. フライウェイト モードはどのようなシナリオで使用されますか?
(1) プログラム内で同様のオブジェクトが多数使用されており、メモリのオーバーヘッドが大きくなります
(2) オブジェクトのほとんどの状態は外部状態に変更でき、外部状態を取り除いた後、多数のオブジェクトを比較的少数の共有オブジェクトに置き換えることができます
3. フライウェイトモードを適用するにはどうすればよいですか?
最初のレイヤーは、主にメモリ内の多数の同様のオブジェクトに適用されます。
2 つ目は DOM レイヤーで適用され、中央イベント マネージャーで 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 } ]);
(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 ? createObjFn.apply(this, arguments) : objectPool.shift(); return obj; }, recover: function() { objectPool.push(obj); } }; }