经典继承和对象池

Classical Inheritance and Object Pooling

本文关键字:对象 继承 经典      更新时间:2023-09-26

我目前正在做一个项目,其中使用了以下继承结构:

var Type = function(a){
  this.a = a;
};
var SubType = function(a){
  Type.call(this, a);
};
SubType.prototype = Object.create(Type.prototype);
SubType.prototype.constructor = SubType;

现在,我正尝试在等式中添加一些对象池。我目前使用的模式类似于(伪代码):

Type.new = function(){
  if object available in pool
    reset popped pool object 
    return pool object
  else
    return new Type()
}
var a = Type.new();
当然,使用这两种模式的问题是,对SubType的构造函数调用不会从Type的池中提取。有没有一种不需要搬到工厂结构的方法?也就是说,在构造函数中,是否有一种方法可以执行以下操作:
var SubType = function(){
  build on top of instanceReturnedFromFunction()
};

知道它并不总是跨上下文一致,我也想保留继承结构,以便instanceof等仍然可以工作:

使用这种模式的问题是对SubType的构造函数调用不会从Type的池中提取

事实上那不是问题,那是必要的。TypeSubType实例确实有不同的原型,你不能互换使用它们(交换原型也不起作用)。
您肯定需要为所有类使用单独的池。您可以毫无问题地使用.new工厂方法——当然,您应该以编程方式创建这些工厂:

function pooledNew() {
    // `this` is the "class" constructor function
    if (!this.pool) this.pool = [];
    var instance = this.pool.length ? this.pool.pop() : Object.create(this.prototype);
    this.apply(instance, arguments); // reset / initialise
    return instance;
}
function makePooling(constr) {
    constr.new = pooledNew;
    constr.pool = [];
    var proto = constr.prototype;
    if (proto.constructor !== constr)
        proto.constructor = constr;
    if (typeof proto.destroy != "function")
        proto.destroy = function destroyInstance() {
            this.constructor.pool.push(this);
        };
    return constr;
}

这些都是为了完美地与子类一起工作而设计的,在您的示例中只需执行

makePooling(Type);
makePooling(SubType);

在ES6中,子类甚至会从它们的父类构造函数中继承new方法。

class Type {
    constructor(a) {
        this.a = a;
    }
    destroy() { // overwriting default behaviour
        this.a = null; // for GC
        this.constructor.pool.push(this);
    }
}
makePooling(Type);
class SubType extends Type {
    // you can use super calls in both "constructor" and "destroy" methods
}