Motivation:
The pattern Unified Access describes a type safe access (reading and writing) to values of a map object (object that maps keys to values) for a such case where values have got different data types.Structure (class model):
The model contains two classes:- MyMap - a class of data store
- Property - an immutable class is a key of the map which provides a type-safe public methods for reading and writting of values
Implementation in Java language
The implementation requires a generic type language support that's why the Java SE 5.0 or more must be used.A MyMap class implements a simple map behavior and it contains two keys NAME and 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>();All keys are an instance of a Property class, however each of them will provide a value of a different type.
protected Object readValue(Property key) { return data.get(key); } protected void writeValue(Property key, Object value) { data.put(key, value); } }
If both classes (MyMap and Property) will be located in the same package, then it is possible to retain their visibility to protected so that no strange object can to use them.
public class Property<VALUE> {This pattern allows a value access by a methods of key only. It is possible to verify the method setValue accepts declared value type to write into map object and then method getValue returns the same data type only.
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);
Usage:
The pattern design can be used like a special delegate of the POJO object. It's useful in case there is to need to refer a set of get method and to avoid a non-type value access by reflection API. Here are some samples of usage in a Java language- The sort method takes a list of items and its keys (e.g. NAME, AGE) for the ordering. A GenericSorter implementation builds an appropriate comparator oneself .
interface GenericSorter { public void sort(List<MyMap> items, Property ... keys); }
- a child of a TableModel interface, which can to take a list of columns by an argument of a method
interface GenericTableModel<MyMap> extends TableModel { public void setColumns(Property ... columns); }
- Because all values of the class MyMap are saved by a single method called writeValue(), it is possible to implement
one validation check for all values. In case the MyMap class becomes a parrent of more classes (they are written in the same pattern desing),
so the method writeProperty() will become a central writing point for all hierarchy of classes.
The point is a true place for inserting common validations, conversions or listeners.
Next method writeValue() can check NULL value and throws an exception in this case.protected Object writeValue(Property key, Object value) { if (value==null) { throw new IllegalArgumentExeption(); } super.writeValue(key, value);
} - Type safe factory can be implemented by removing the method writeValue() and by different implementation of the original method readValue().
Sample of the use:
DomainObject do = MyMap.DOMAIN_KEY.newInstance(map); // renamed method getValue()
Both projects are available include a source code on SourceForge.net under an open license since 2007-10-24.
The pattern design was slightly extended; a final solution is described by two interfaces Another projects using the pattern:
About Author:
- You can write questions or other messages to me by a blog http://ujorm.blogspot.com/.
- There exists some more free applications on an authors home page http://ponec.net/ .
- A contact e-mail: ponec@ujorm.com
PPone(c) 2007-2011