I created a class to handle these requirements in a generic way. I thought of this new "value class" as containing a capricious value, and so called it Fickle, which is a parameterized class. It is not synchronised, so beware when multithreading.
Here is the code:
import java.util.Collections; import java.util.Set; import java.util.WeakHashMap; public class Fickle<T> { private T _value; private final Set<OnChangeListener<T>> _listeners; public Fickle(final T value) { _value = value; _listeners = Collections.newSetFromMap( new WeakHashMap<OnChangeListener<T>, Boolean>()); } public void addOnChangeListener(final OnChangeListener<T> listener) { _listeners.add(listener); } public void setValue(final T newValue) { _value = newValue; for (OnChangeListener<T> l : _listeners) if (l != null) l.onChangeEvent(newValue); } public T getValue() { return _value; } public interface OnChangeListener<T> { void onChangeEvent(T newValue); } }
As you can see I have used a Set made from a WeakHashMap to store the event listeners. This is to ensure that Fickle objects don't create memory leaks. As the reference to the listener is weak, when a listener object is no longer in use anywhere else in the code then it will automatically be removed from the set. This is a very cool Java feature. However, what this means is that you must have a strong (normal) reference to the listener object, otherwise it will be deleted. Here is an example of how to use the Fickle class:
class MrsClass { private float _doubleVal; public MrsClass(final Fickle<Float> capVal) { // Initialize the member variable. setVal(capVal.getValue()); // Handle the on change event. capVal.addOnChangeListener(new Fickle.OnChangeListener<Float>() { public void onChangeEvent(Float newValue) { setVal(newValue); } }); } private void setVal(float val) { _doubleVal = val * 2.0f; } public float getDoubleVal() { return _doubleVal; } } class MrMain { public static void main(String[] args) { Fickle<Float> val; val = new Fickle<Float>(1.0f); MrsClass mrs = new MrsClass(val); float doubled = mrs.getDoubleVal(); // should equal 2.0f val.setValue(3.5f); doubled = mrs.getDoubleVal(); // should equal 7.0f // By dereferencing the MrsClass object the // listener will be automatically removed from // the listener Set by the WeakHashMap class. mrs = null; } }
So this is effectively an encapsulation of the Observer pattern.
No comments:
Post a Comment