Flyweight是一种共享数据内存的模式。
Flyweight模式是将一些公有属性从个人中剔除,放在共享的对象当中。
下面以一个项目实例,通过不断的改进,以显示Flyweight模式的优点。
现在我们想做一个电脑生产程序,用以生产电脑,电脑的一般有生产商,机型,CPU类型,内存,和型号。
我们的最初代码如下:
// 电脑类 var Computer = function (make, model, processor, memory, tag) { this.make = make; this.model = model; this.processor = processor; this.memory = memory; this.tag = tag; } // 测试生产两台不同的电脑 var computer1 = new Computer("Dell", "Studio XPS", "Intel", "4G", "Y755P"); var computer2 = new Computer("Dell", "Studio XPS", "Intel", "8G", "Y755P"); console.log(computer1); console.log(computer2);
对代码简单的分析,我们可以发现,两台不同的电脑的前三个属性,品牌,机型和CPU都是一样的。而我们却每次都为其重新定义赋值。
试想一下,如果这样有一百上千台的电脑,那对内存来说就是一笔不小的开销。我们可不可以将这些相同的属性共有化呢?
// 电脑类 var Computer = function (make, model, processor, memory, tag) { // 引用共享单元中的数据 if(make + model + processor === "DellStudio XPSIntel"){ this.flyweight = flyweight1; } this.memory = memory; this.tag = tag; } // 共享单元 var flyweight = { make: 'Dell', model: "Studio XPS", processor: "Intel" } // 测试 var computer1 = new Computer("Dell", "Studio XPS", "Intel", "4G", "Y755P"); var computer2 = new Computer("Dell", "Studio XPS", "Intel", "8G", "Y755P"); console.log(computer1); console.log(computer2);
在这里我们将共有几乎固定的属性从类中剔除,建立了一个很生硬的对象flyweight以存放他们用来共享。就这样,虽然新生产每台电脑都有5个属性,但其中前三个属性都是共享flyweight对象中的数据。节省了内存开支。尤其这样前三个属性相同的电脑比较多时,这已经就是Flyweight的精髓了,只是我们的模式还很初步。
继续我们的思路,如果我们需要再多一个共享单元呢,难道重新创建一个对象?不是的。此时我们用一个类创建各种享元,且用一个对象作为列表来存放来会更好一些。
// 享元列表 var flyweightList = {}; var Computer = function (make, model, processor, memory, tag) { if(flyweightList[make+model+processor]){ // 享元列表中存在,直接引用 this.flyweight = flyweightList[make+model+processor]; }else { // 不存在,创建新的享元对象并存入列表中 this.flyweight = new Flyweight(make, model, processor); flyweightList[make+model+processor] = this.flyweight; } this.memory = memory; this.tag = tag; } // 享元类 function Flyweight (make, model, processor) { this.make = make; this.model = model; this.processor = processor; }; var computer1 = new Computer("Dell", "Studio XPS", "Intel", "4G", "Y755P"); var computer2 = new Computer("Dell", "Studio XPS", "Intel", "8G", "Y755P"); var computer3 = new Computer("HP", "Envy", "Intel", "2G", "801632312"); console.log(computer1); console.log(computer2); console.log(computer3);
这样其实已经很不错了,只是享元列表作为一个全局变量似乎不太好,在比较高级的享元模式运用,我们还需要一些其他的方法,如获取享元中的数量等。进一步我们可以用模块模式将享元包裹一下。
function Flyweight (make, model, processor) { this.make = make; this.model = model; this.processor = processor; }; var FlyweightFactory = (function(){ // 私有 var flyweightList = {}; return { // 新增享元 addFlyweight: function (make, model, processor){ if(!flyweightList[make+model+processor]){ flyweightList[make+model+processor] = new Flyweight(make, model, processor); } return flyweightList[make+model+processor]; }, // 计数 count: function(){ var count = 0; for (var f in flyweightList) count++; return count; } } })() var Computer = function (make, model, processor, memory, tag) { this.flyweight = FlyweightFactory.addFlyweight(make, model, processor) this.memory = memory; this.tag = tag; } var computer1 = new Computer("Dell", "Studio XPS", "Intel", "4G", "Y755P"); var computer2 = new Computer("Dell", "Studio XPS", "Intel", "8G", "Y755P"); var computer3 = new Computer("HP", "Envy", "Intel", "2G", "801632312"); console.log(computer1); console.log(computer2); console.log(computer3); console.log(FlyweightFactory.count())
享元是一种非常常用的设计模式,对性能的优化有很大的作用。