1. Definition
The flyweight mode is a mode used for performance optimization. The core is to use sharing technology to effectively support a large number of fine-scale objects.
In JavaScript, browsers, especially mobile browsers, do not allocate much memory, so how to save memory becomes a very meaningful thing.
Flyweight mode is an optimization mode that trades time for space
2. In what scenarios is flyweight mode used?
(1) A large number of similar objects are used in the program, causing a large memory overhead
(2) Most of the state of an object can be changed to external state. After stripping off the external state, a large number of objects can be replaced with relatively few shared objects
3. How to apply flyweight mode?
The first one is applied on the data layer, mainly on a large number of similar objects in memory;
The second is applied at the DOM layer. Flyweight can be used in the central event manager to avoid attaching event handlers to each child element in the parent container.
Flyweight pattern requires that the properties of an object be divided into internal state and external state.
Internal state is independent of the specific scene, usually does not change, and can be shared by some objects;
External state depends on the specific scenario and changes based on the scenario. External state cannot be shared.
Factory mode often appears in Flyweight mode. Flyweight’s internal state is used for sharing. Flyweight factory is responsible for maintaining a Flyweight pool (pattern pool) to store internal state objects.
Disadvantages: If the number of objects is small, it may increase the system overhead and make the implementation more complex!
4. Example: File upload
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. Supplement
(1) Directly change the formal parameter Demo
function f1() { var obj = {a: 1}; f2(obj); console.log(obj); // {a: 1, b: 2} } function f2(obj) { obj.b = 2; } f1();
(2) Object pool, is also a performance optimization solution. It has some similarities with the flyweight mode, but there is no process of separating internal state and external state.
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); } }; }
I hope this article will be helpful to everyone learning JavaScript programming.