Object Pool


V této části se podíváme na Object Pool. Tento návrhový vzor slouží k uchovávání použitých objektů, abychom je v budoucnu mohli znovu použít a nemuseli vytvářet nové instance. Object Pool nepatří mezi Gang of Four návrhové vzory, ale rozhodně jsem jej na těchto webových stránkách chtěl mít. Používal jsem jej totiž ještě předtím, než jsem se návrhové vzory začal učit a můžu říct, že dokáže být hodně užitečný.

Proč Object Pool použít

Návrhový vzor Object Pool můžeme použít, když opakovaně vytváříme instance nějaké třídy a tyto instance jsou v našem programu jen určitou dobu. Tvorba objektu může být náročná a může nám zpomalovat program. Proto si můžeme použité objekty někde ukládat, a když budeme potřebovat nový objekt, tak si namísto vytváření nové instance jen vezmeme objekt, který jsme již v minulosti použili.

Object Pool slouží k vytváření a uchovávání instancí nějaké třídy. Když potřebujeme novou instanci, tak řekneme Object Poolu aby nám ji dal, a když už ji nebudeme potřebovat, tak ji Object Poolu vrátíme. Object Pool nám dává buď nové instance, když zrovna nemá žádné k dispozici, nebo inicializuje již použité.

Příklad - Znovupoužití objektů namísto vytváření nových

Následující ukázka Object Pool ukazuje, představuje jej třída ObjectPool. Při vytváření Object Poolu si určujeme, jaké instance třídy bude Object Pool uchovávat. V našem příkladu si vytváříme Object Pool pro objekty třídy Strela. Object Pool obsahuje metody ziskat a vratit. Metodu ziskat můžeme použít k získání objektu a metodu vratit můžeme použít k vrácení objektu, když už jej nepotřebujeme.

class ObjectPool {
    constructor(konstruktor) {
        // uložení konstruktoru pro vytvoření nového objektu
        this._konstruktor = konstruktor;
        // v tomto poli se budou uchovávat použité objekty
        this._objekty = [];
    }

    // metoda k získání objektu z Object Poolu
    ziskat() {
        // pokud Object Pool neobsahuje žádné použité objekty, tak se vytvoří nový objekt
        if (this._objekty.length === 0) return new this._konstruktor();

        // získání objektu z pole obsahující použité objekty
        const objekt = this._objekty.pop();
        // inicializace objektu
        objekt.init();
        return objekt;
    }

    // metoda pro vrácení použitého objektu zpět do Object Poolu
    vratit(objekt) {
        // zresetování objektu
        objekt.reset();
        // uchování objektu pro znovupoužití
        this._objekty.push(objekt);
    }
}

class Strela {
    constructor() {
        this.init();
        this.pouzita = false;
    }

    // tato metoda je volána Object Poolem
    // pro inicializaci použitého objektu
    init() {
        this.x = 0;
        this.x = 0;
    }

    // tato metoda je volána Object Poolem
    // při vrácení použitého objektu
    reset() {
        // toto by se dalo dělat i v init metodě, metoda reset slouží hlavně
        // k tomu, aby se třeba vyprázdnilo nějaké pole, které objekt obsahuje
        // a uvolnila se tak paměť již při vrácení objektu do Object Poolu
        this.pouzita = false;
    }

    pouzit(x, y) {
        if (this.pouzita) return;

        console.log("něco se provede...")
        this.x = x;
        this.y = y;

        this.pouzita = true;
    }
}


// vytvoření Object Poolu pro třídu Strela
const objectPool = new ObjectPool(Strela);

// získání objektu z Object Poolu
const strela = objectPool.ziskat();
strela.pouzit();

// vrácení objektu do Object Poolu
objectPool.vratit(strela);

// získání objektu z Object Poolu
const strela2 = objectPool.ziskat();
strela2.pouzit();