2015-07-12 17 views
5

Attualmente sto lavorando su un progetto in cui viene utilizzata la seguente struttura di ereditarietà:eredità classica e pool di oggetti

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; 

Ora, sto cercando aggiungere un po 'il pool di oggetti per l'equazione. Il modello Attualmente sto usando opere qualcosa di simile (pseudocodice):

Type.new = function(){ 
    if object available in pool 
    reset popped pool object 
    return pool object 
    else 
    return new Type() 
} 
var a = Type.new(); 

Naturalmente, il problema con l'utilizzo di questi due modelli è che le chiamate costruttore sul sottotipo solito traggono dal pool di Type. C'è un modo per aggirare questo senza passare a una struttura di fabbrica? Cioè c'è un modo, in un costruttore, di fare qualcosa sulla falsariga di:

var SubType = function(){ 
    build on top of instanceReturnedFromFunction() 
}; 

Sapendo che non è sempre coerente in tutti i contesti, mi piacerebbe piacerebbe anche per preservare la struttura di ereditarietà in modo che instanceof ecc continuerà a funzionare :

+0

Che cos'è una "struttura di fabbrica" ​​e perché vuoi evitarlo? – Bergi

+0

Per struttura di fabbrica, intendo refactoring da costruttori/nuovo a qualcosa sulla falsariga di 'function Type (a) {return {a: a}}'. Per quanto riguarda il motivo: comporterebbe una quantità di refactoring, e escluderebbe l'uso di alcuni operatori incorporati (istanza di ecc.) – Nodehead

+0

Ah, capisco. Pensavo intendessi la fabbrica di "Type.new' ... – Bergi

risposta

4

Il problema con l'utilizzo di questo modello è che il costruttore chiede SubType solito attingere da piscina Type s'

In realtà questo non è un problema, che è una necessità. Le istanze Type e SubType hanno diversi prototipi, non è possibile utilizzarli in modo intercambiabile (e swapping prototypes doesn't work either).
Hai sicuramente bisogno di piscine separate per tutte le tue lezioni. Ed è possibile utilizzare questo approccio .new fabbrica senza problemi - anche se naturalmente è necessario creare quelle fabbriche programatically:

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; 
} 

Questi sono progettati per funzionare perfettamente con la creazione di sottoclassi, nel tuo esempio basta fare

makePooling(Type); 
makePooling(SubType); 

In ES6, anche le sottoclassi erediterebbero il metodo new dai loro costruttori di superclasse.

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 
} 
+1

Brillante. Grazie per le informazioni. Non ho ancora il rappresentante per votare la risposta, ma l'ho contrassegnato come accettato: risponde alla mia domanda! Grazie ancora. – Nodehead

+1

@MrMe: Ora hai il privilegio :-) Richiedente ben scritto, benvenuto su Stack Overflow! – Bergi