* 适应条件
** 一个程序中使用了大量的相似对象 造成大的内存开销
** 对象的大多数状态都可以变为外部状态
** 剥离出对象的外部状态之后, 可以使用相对较少的共享对象取代大量对象
* 上传文件的例子:
index.html
<html> <head> <meta charset="UTF-8"> <title>一个上传多个文件的例子</title> </head> <body> <script src="js/upload.js"></script> </body> </html>
js/upload.js
function Upload(uploadType) { this.uploadTpye = uploadType; } var UploadFactory = (function() { var c = {}; // cache return { // @param t: uploadType create: function(t) { if (c[ t ]) { return c[ t ]; } return c[ t ] = new Upload( t ); } } })(); var uploadManager = (function() { // uploadDatabase var db = {}, autoInc = 1; return { add: function(uploadType, file) { var o = UploadFactory.create(uploadType), id = autoInc++; var dom = document.createElement('div'); dom.setAttribute("data-id", id); // debug dom.innerHTML = "<span>文件名称: " + file.fileName + ", 文件大小: " + file.fileSize + "</span>" + "<button class='delFile'>删除</button>"; dom.querySelector(".delFile").onclick = function() { o.delFile(id); }; document.body.appendChild(dom); db[ id ] = { fileName: file.fileName, fileSize: file.fileSize, dom: dom }; return o; }, setExternalState: function(id, o) { var uploadData = db[id]; Object.keys(uploadData).forEach(function(prop) { o[ prop ] = uploadData[ prop ]; }); } } })(); Upload.prototype.delFile = function(id) { uploadManager.setExternalState(id, this); if (this.fileSize < 3000) { return this.dom.parentNode.removeChild(this.dom); } if (window.confirm('确定要删除该文件吗?' + this.fileName)) { return this.dom.parentNode.removeChild(this.dom); } } window.startUpload = function(uploadType, files) { files.forEach(function(file) { var uploadObj = uploadManager.add(uploadType, file); }); }; startUpload('plugin', [ { fileName: '1.txt', fileSize: 1000 }, { fileName: '2.html', fileSize: 3000 }, { fileName: '3.txt', fileSize: 5000 } ]); startUpload('flash', [ { fileName: '1.txt', fileSize: 1000 }, { fileName: '2.html', fileSize: 3000 }, { fileName: '3.txt', fileSize: 5000 } ]);