public abstract class Handle extends java.lang.Object implements Copiable, java.lang.Cloneable
This class calls for a distinction between object identity and object state. Made this distinction, it becomes possible to share the same state across different objects upon copy operations. When an object is updated, a new state representation is bound to that object, while the other objects can still share the previous state. This way we can have shallow copy with the semantics of deep copy. This can result in dramatically reduced memory footprint when:
For example, think of a class R
that represents a rectangle in
the plane with 4
integer fields x, y, w, h
,
and say you want to use instances of this class to describe an ROI (region of
interest) selection in a given image 3D-stack composed of 100
planes each plane would contain a rectangle selection and all those
selections would make up your ROI. Let's assume that the initial selection is
a discrete 3D-rectangle that spans all planes in the stack you would
have one rectangle per plane, every rectangle would have exactly the same
state, say s[x=0, y=0, w=3, h=4]
. Moreover, let's assume that
you will have to modify slightly this initial ROI in order to get the final
selection for example by resizing/moving a couple of rectangles within
the selection. Now, when you start off with the initial selection, you could
decide to clone an initial master object whose state is s
this way, you can later modify one of the copies without affecting the
others. However, because Java makes no distinction between object
identity and state, you would have in memory 100
references
and 100
copies of the same logical state s
,
while you actually only need one.
The purpose of this class is to help you save memory in situations like that just described by approximating the semantics of the well known Handle/Body and Counted Body idioms often found in C++ programs. A given class abstraction is implemented by two actual classes which replicate the same class interface. One class, the Handle, takes on the role of an object identifier and forwards all calls to the other class, the Body, which implements the actual functionality. Clients can only access instances of the Handle which can all share the same Body object whenever appropriate.
The way this works in our case is pretty easy. An Handle class extends this
base Handle
class and provides a reference to an instance of
the corresponding Body class. The concrete Handle class exposes the same
interface as its corresponding Body (this is not an absolute requirement, but
usually an implementation trade-off) and has no state in fact,
the state is hold by the associated Body object. The Handle just forwards to
the Body any call that only reads the Body's state. However, it must call the
breakSharing
protected method before
forwarding any call that modifies the Body's state. It is crucial that
concrete Handle
classes stick to this rule. In fact, the
copy
method simply rebinds a new Handle
to the
existing Body, so subclasses must notify any incumbent change to the Body's
state for the Handle
to break state sharing. Lastly, it's also
fundamental that the Body class implements the Copiable
interface
correctly for all this to work properly.
Modifier | Constructor and Description |
---|---|
protected |
Handle(Copiable body)
Subclasses use this constructor to specify the Body instance this handle
will be paired up with.
|
Modifier and Type | Method and Description |
---|---|
protected void |
breakSharing()
Subclasses must call this method before forwarding any call that
modifies the Body's state.
|
java.lang.Object |
copy()
Returns a deep copy of this object.
|
protected java.lang.Object |
getBody()
Returns a reference to the Body object that is currently paired
up with this handle.
|
protected Handle(Copiable body)
body
- Reference to the Body object. Mustn't be null
.protected java.lang.Object getBody()
breakSharing
method has been invoked. For this
reason, subclasses mustn't cache a reference to the object returned by
this method. Moreover, subclasses must never leak out a reference to the
returned Body object.protected final void breakSharing()
public final java.lang.Object copy()