Motivace:
Návrhový vzor Unified Access Pattern popisuje typově bezpečný přístup (čtení a zápis) k hodnotám objektu mapa (objekt mapující klíče k hodnotám) v případě, že datové typy hodnot se vzájemně liší.Struktura (class model):
Model obsahuje dvě třídy:- MyMap - jednoduchá mapa s relacemi: klíč - hodnota
- Property - třída reprezentující klíč mapy MyMap
Implementace v jazyce Java
Protože implementace vyžaduje podporou generických datových typů, je třeba použít Java SE 5.0, nebo vyšší.Třída MyMap implementuje jednoduchou mapu a obsahuje dva klíče NAME a AGE.
import java.util.*; public class MyMap { public static final Property<String> NAME = new Property<String>(); public static final Property<Integer> AGE = new Property<Integer>(); private Map<Property, Object> data = new HashMap<Property, Object>();Všechny klíče jsou instance třídy Property, nicméně každý z nich bude poskytovat hodnotu jiného datového typu.
protected Object readValue(Property key) { return data.get(key); } protected void writeValue(Property key, Object value) { data.put(key, value); } }
Pokud budou ležet obě třídy MyMap a Property ve stejném balíku, je možné ponechat viditelnost metod writeValue() a readValue() na protected, aby je nemohl používat cizí objekt.
public class Property<VALUE> {V návrhovém vzoru se přistupuje k hodnotám mapy pouze pomocí metod klíče. Na následujícím kódu lze ověřit, že metoda setValue dovolí přiřadit do mapy pouze objekt deklarovaného typu a metoda getValue tento typ zase vrací.
public void setValue(MyMap map, VALUE value) { map.writeValue(this, value); } public VALUE getValue(MyMap map) { return (VALUE) map.readValue(this); } }
MyMap map = new MyMap();
MyMap.NAME.setValue(map, "Peter Prokop"); MyMap.AGE .setValue(map, 22); String name = MyMap.NAME.getValue(map); int age = MyMap.AGE.getValue(map); System.out.println(name + " is " + age);
Praktické využití:
Návrhový vzor může nahradit klasické POJO objekty. Smysl to má v případě, kdy je třeba odkazovat se na metodu (set/get) objektu, nikoli na jeho hodnotu. Tři konkrétní příklady využití v jazyku Java:- Metoda pro řazení seznamu řádků převezme kromě seznamu objektů také seznam vlastností (například NAME, AGE), podle kterých se řazení provádí.
Sorter si sám sestaví odpovídající komparátor.
interface GenericSorter { public void sort(List<MyMap> items, Key ... keys); }
- potomek rozhraní TableModel, který umí převzít seznam sloupců pomocí argumentu metody
interface GenericTableModel<MyMap> extends TableModel { public void setColumns(Property ... columns); }
- Je zřejmé, že ve třídě MyMap se všechny hodnoty ukládají jedinou metodou writeProperty().
Pokud se ale třída MyMap v stane rodičem dalších tříd (napsaných v duchu návrhového vzoru),
tak metoda writeProperty() se stane centrálním místem pro zápis celé hierarchie objektů.
Takové místo je ideální pro pro vkládání validací, konverzí a listenerů společných pro všechny zůčastněné objekty.
Následující metoda readProperty() zaměňuje všechny nedefinované hodnoty typu Integer za 0. V této ukázce třída Property vrací návratový typu hodnoty pomocí metody getType().protected Object readValue(Property key) { Object result = super.readValue(key);
if (result==null && key.getType()==Integer.class ){ return 0; } else { return result; } }
Oba projekty jsou dostupné včetně zdrojových kódů na SourceForge.net pod otevřenou licencí ode dne 2007-10-24.
Návrhový vzor byl v těchto projektech rozšířen o další metody a formálně je popsán dvojicí rozhraní
O autorovi:
- Pro připomínky, dotazy či jiné zprávy můžete použít blog http://ujorm-cs.blogspot.com/.
- Na domovské stránce autora lze najít některé jeho další volně šiřitelné programy a jiné informace, odkaz je: http://ponec.net/ .
- Kontaktní email: ponec@ujorm.com
PPone(c) 2007