Návrhový vzor Object pool (Fond) použijeme, potřebujeme-li omezit počet vytvářených instancí, jejichž výroba je časově náročná, ale nepotřebujeme jich mnoho najednou. Pool upřednostňuje recyklaci (znovuvyužití) objektů před konstrukcí nových instancí.
Princip
Jádrem vzoru je samotná třída fondu, která zajišťuje vydávání a uchovávání instancí. Potřebuje-li aplikace instanci daného typu, obratí se na fond a ten jí tuto instanci propůjčí. V okamžiku, kdy již tato instance není zapotřebí, tak ji aplikace vrátí zpět do fondu pro budoucí využití.
Aspekty implementace fondu
Při programování fondu je zapotřebí brát ohled na přesné potřeby dané aplikace, zejména pak na následující aspekty.
Kapacita
Důležitým rozhodnutím z hlediska implementace je kapacita fondu, respektive, zda-li se může v čase měnit. Fond buď může být implementován velmi triviálně, kdy má omezenou předem definovanou kapacitu, nebo může obsahovat složitou logiku, která na základě potřeb aplikace zvyšuje kapacitu fondu (a dovytváří nové instance) nebo snižuje kapacitu fondu (a nechává instance smazat).
Blokování výběru
Druhým aspektem je chování fondu v momentě, kdy narazí na strop počtu instancí (je-li definován). Fond v tento okamžik může buď volání blokovat a čekat na vrácení některé instance, vrátit null, nebo vyhodit výjimku.
Garbage kolekce
Je zapotřebí si uvědomit, že pooling instancí má také vedlejší efekty z hlediska garbage kolekce a to zejména u generačních kolektorů. Život instancí spravovaných fondem by bez použití tohoto vzoru byl vetšinou velmi krátký – garbage collector by je sebral po jejich použití a zahození. V případě použití fondu jsou ale instance fakticky nesmrtelné a postupně se propracují do starší generace, čímž se komplikuje její kolekce.
Životní cyklus instancí
Posledním aspektem je životní cyklus instancí. Může se totiž stát, že fond nerozhoduje o tom, zda-li nebude některý ze zdrojů dané instance zneplatněn. Příkladem v tomto ohledu mohou být spojení, která mohou být vypovězena z druhé strany (například databázové spojení). Fond proto musí v příslušných případech také ověřovat platnost jednotlivých instancí.
Příklad
Implementujte fond, který bude spravovat fixní uživatelem zadané množství instancí objektu databázového spojení (spojení nemůže být uzavřeno ze strany databáze). V případě, že klient zažádá o spojení v okamžiku, kdy je fond prázdný, dostane prázdnou referenci (null)
Kód
01.
/**
02.
* Demostrace vzoru Object pool
03.
* Fond ma fixni kapacitu
04.
* @author Pavel Micka
05.
*/
06.
class
Pool{
07.
private
Queue<DBConnection> queue;
08.
09.
public
Pool(
int
capacity) {
10.
this
.queue =
new
LinkedList<DBConnection>();
11.
12.
for
(
int
i =
0
; i < capacity; i++){
13.
queue.add(
new
DBConnection());
14.
}
15.
}
16.
/**
17.
* Vrati spojeni s databazi
18.
* @return spojeni s DB, @null pokud je pool prazdny
19.
*/
20.
public
synchronized
DBConnection acquireObject(){
21.
return
queue.poll();
22.
}
23.
/**
24.
* Vrati spojeni s DB do poolu
25.
* @param conn
26.
*/
27.
public
synchronized
void
releaseObject(DBConnection conn){
28.
queue.add(conn);
29.
}
30.
}
31.
32.
/**
33.
* Trida reprezentujici spojeni s DB
34.
* @author Pavel Micka
35.
*/
36.
class
DBConnection{
37.
/**
38.
* "Provede" select z databaze
39.
*/
40.
public
void
select(){
41.
System.out.println(
"SELECT * FROM Table WHERE id = "
+ ((
int
)(Math.random()*
100
)));
42.
}
43.
}