Identity Map
Situace
Trvalé úložiště dat obsahuje entity, jejichž obrazy se vytváří
v aplikaci. Tyto entity jsou rozlišeny klíčem. Pod trvalým úložištěm si
lze představit například databázi, pod entitami zákazníky a pod klíčem
jejich ID. Problém
Nic nebrání tomu, aby aplikace volně vytvářela instance entit a ty
rozesílala do různých částí programu. Případná změna jedné takové
instance se neprojeví v ostatních instancích a dojde k porušení principu SSOT. Také je nutné
při každém požadavku na entitu načítat aktuální data z trvalého
úložiště, což je zbytečné, pokud se uložená instance mezitím
nezměnila.
kód v jazyce Java - Zobrazit
-
public Customer getCustomer(long id)
-
{
-
// ...
-
// načíst data z
databáze
-
// SELECT * FROM customer WHERE id =
?
-
// ...
-
-
Customer entity = new
Customer();
-
// ...
-
entity.setName(result.getString("name"));
-
entity.setSurname(result.getString("surname"));
-
// ...
-
return entity;
-
}
-
-
public void
problem()
-
{
-
Customer c1 = getCustomer(1);
-
Customer c2 = getCustomer(1);
-
-
c1.setName("John");
-
-
// problém: která instance je teď
ta správná
-
// instance c1 má ještě staré
jméno
-
// instance c2 obsahuje již nové
jméno
-
}
Řešení
Řešení tohoto problému spočívá v odstínění programu od
vytváření instancí. Vznikne nová třída, která bude instance entit
spravovat a vytvářet je pouze tehdy, když instance entity s požadovaným
klíčem neexistuje. V podstatě se jedná o prostou
vyrovnávací paměť.
Varianty
- implicitní – jedna mapa pro každý typ entity
- explicitní – pouze jedna univerzální mapa, typ entity
se specifikuje později
Implementace
kód v jazyce Java - Zobrazit
-
import java.util.HashMap;
-
import java.util.Map;
-
-
/**
-
* Identity Map.
-
*
-
* @author Vojtěch
Hordějčuk
-
* @param <K>
-
* třída klíče (např.
Long)
-
* @param <V>
-
* třída entity (např.
Customer)
-
*/
-
public class
IdentityMap<K, V>
-
{
-
/**
-
* cache obsahující
jedinečné instance entit
-
*/
-
private final Map<K, V> cache;
-
/**
-
* DAO pro načítání entit
z trvalého úložiště
-
*/
-
private final DAO<V> dao;
-
-
/**
-
* Vytvoří novou
instanci.
-
*
-
* @param dao
-
* DAO pro zadaný typ
entit
-
*/
-
public IdentityMap(final DAO<V> dao)
-
{
-
this.cache = new HashMap<K, V>();
-
this.dao = dao;
-
}
-
-
/**
-
* Vrátí jedinečnou
instanci pro zadaný klíč. Pokud instance neexistuje, bude
-
* vytvořena a uložena do
cache.
-
*
-
* @param key
-
* klíč
-
* @return jedinečná
instance pro zadaný klíč
-
*/
-
public V getInstance(final K key)
-
{
-
if (!this.cache.containsKey(key))
-
{
-
// hodnota s tímto
klíčem není v cache
-
// bude vytvořena nová
instance
-
-
final V fresh =
dao.load(key);
-
this.cache.put(key, fresh);
-
return
fresh;
-
}
-
-
// vrátit již existující
hodnotu z cache
-
-
return this.cache.get(key);
-
}
-
}
Reference