Hi Mel
Martinez, Mel - 1004 - MITLL schrieb:
This goes to some basic principles of object design.
When you add state members to an object you should think about the life
cycle of the member. I try to follow three basic rules:
1) Favor immutability. I.E. - set state upon initialization and don't allow
it to change. No setters or other mutators (and make the object 'final').
Immutable objects are gold for optimizing for speed and memory efficiency.
2) Use accessor methods. Even for internal access to a member field, use a
getter method. This allows you to optimize access to the member or to use
lazy initialization when appropriate. Let the compiler and runtime optimize
the method access away. You are kidding yourself if you think it is faster
to directly access a member field. This is not C.
3) If an object is to have mutable state, all mutation of a member should be
through a single point - a setter or a specific mutator. Do not ever assign
the value of the member directly. This allows you to implement any caching
or optimizations in one place.
Agreed.
So per your question below, so long as all attributes are properly wrapped
in getter/setters, then the act of pulling their values out of the
underlying dictionary stream and storing them in instance fields is simply
done within the accessors. If you mutate a field, the setter updates the
dictionary AND the member field. Per Jukka's comments, that implementation
detail is completely hidden behind the getter/setter abstractions.
Consider the following: A PDAnnotation and a PDStructureElement object
give access to PDPage objects wrapping the same COSDictionary. PDPage
objects give access to their contents (PDStream). All of these members
are lazy initialized.
PDAnnotation:
private PDPage page;
public PDPage getPage()
{
if (this.page == null)
{
this.page = new PDPage(
this.getCOSDictionary().getDictionaryObject(COSName.P));
}
}
PDStructureElement:
private PDPage page;
public PDPage getPage()
{
if (this.page == null)
{
this.page = new PDPage(
this.getCOSDictionary().getDictionaryObject("Pg"));
}
}
PDPage:
private PDStream contents;
public PDStream getContents()
{
if (this.contents == null)
{
this.contents = PDStream.createFromCOS(
this.getCOSDictionary().getDictionaryObject(COSName.CONTENTS));
}
return this.contents;
}
public void setContents(PDStream contents)
{
this.contents = contents;
this.getCOSDictionary().setItem(COSName.CONTENTS, contents);
}
Now,
PDAnnotation annotation = ...;
PDStructureElement se = ...;
PDPage pageA = annotation.getPage();
PDPage pageSE = se.getPage();
// COSDictionary for pageA is the same as for pageSE
PDStream streamA = pageA.getContents();
PDStream streamSE = pageSE.getContents();
PDStream stream3 = ...;
pageA.setContents(stream3);
This last operation (change of pageA's contents) will not have any
influence on pageSE's contents, although the COSDictionary wrapped by
both PDPage objects will be changed. So pageSE's contents member is not
in synch with the COSDictionary's entry any more.
--
Johannes Koch
Fraunhofer Institute for Applied Information Technology FIT
Web Compliance Center
Schloss Birlinghoven, D-53757 Sankt Augustin, Germany
Phone: +49-2241-142628 Fax: +49-2241-142065