KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > util > Freezable


1 /*
2  ******************************************************************************
3  * Copyright (C) 200-2006, International Business Machines Corporation and *
4  * others. All Rights Reserved. *
5  ******************************************************************************
6 */

7 package com.ibm.icu.util;
8
9 /**
10  * <pre>
11  * DRAFT
12  * Copyright (C) 2005, International Business Machines Corporation and
13  * others. All Rights Reserved.
14  * </pre>
15  *
16  * Provides a flexible mechanism for controlling access, without requiring that
17  * a class be immutable. Once locked, an object can never be unlocked, so it is
18  * thread-safe from that point onward. The implementation of both methods must
19  * be synchronized. Once the object has been locked, it must guarantee that no
20  * changes can be made to it. Any attempt to alter it must raise an
21  * UnsupportedOperationException exception. This means that when the object
22  * returns internal objects, or if anyone has references to those internal
23  * objects, that those internal objects must either be immutable, or must also
24  * raise exceptions if any attempt to modify them is made. Of course, the object
25  * can return clones of internal objects, since those are safe.
26  * <h2>Background</h2>
27  * <p>
28  * There are often times when you need objects to be objects 'safe', so that
29  * they can't be modified. Examples are when objects need to be thread-safe, or
30  * in writing robust code, or in caches. If you are only creating your own
31  * objects, you can guarantee this, of course -- but only if you don't make a
32  * mistake. If you have objects handed into you, or are creating objects using
33  * others handed into you, it is a different story. It all comes down to whether
34  * you want to take the Blanche Dubois approach (&quot;depend on the kindness of
35  * strangers&quot;) or the Andy Grove approach (&quot;Only the Paranoid
36  * Survive&quot;).
37  * </p>
38  * <p>
39  * For example, suppose we have a simple class:
40  * </p>
41  *
42  * <pre>
43  * public class A {
44  * protected Collection b;
45  *
46  * protected Collection c;
47  *
48  * public Collection get_b() {
49  * return b;
50  * }
51  *
52  * public Collection get_c() {
53  * return c;
54  * }
55  *
56  * public A(Collection new_b, Collection new_c) {
57  * b = new_b;
58  * c = new_c;
59  * }
60  * }
61  * </pre>
62  *
63  * <p>
64  * Since the class doesn't have any setters, someone might think that it is
65  * immutable. You know where this is leading, of course; this class is unsafe in
66  * a number of ways. The following illustrates that.
67  * </p>
68  *
69  * <pre>
70  * public test1(SupposedlyImmutableClass x, SafeStorage y) {
71  * &lt;font color=&quot;#0000FF&quot;&gt; &lt;b&gt;// unsafe getter&lt;/b&gt;
72  * &lt;/font&gt; A a = x.getA();
73  * Collection col = a.get_b();
74  * col.add(something);&lt;font color=&quot;#0000FF&quot;&gt; // a has now been changed, and x too
75  * &lt;/font&gt;
76  * &lt;font color=&quot;#0000FF&quot;&gt;&lt;b&gt;// unsafe constructor&lt;/b&gt;&lt;/font&gt;
77  * a = new A(col, col);
78  * y.store(a);
79  * col.add(something);&lt;font color=&quot;#0000FF&quot;&gt; // a has now been changed, and y too
80  *
81  * &lt;/font&gt;}
82  * </pre>
83  *
84  * <p>
85  * There are a few different techniques for having safe classes.
86  * </p>
87  * <ol>
88  * <li>Const objects. In C++, you can declare parameters const.</li>
89  * <li>Immutable wrappers. For example, you can put a collection in an
90  * immutable wrapper.</li>
91  * <li>Always-Immutable objects. Java uses this approach, with a few
92  * variations. Examples:
93  * <ol>
94  * <li>Simple. Once a Color is created (eg from R, G, and B integers) it is
95  * immutable.</li>
96  * <li>Builder Class. There is a separate 'builder' class. For example,
97  * modifiable Strings are created using StringBuffer (which doesn't have the
98  * full String API available). Once you want an immutable form, you create one
99  * with toString().</li>
100  * <li>Primitives. These are always safe, since they are copied on input/output
101  * from methods.</li>
102  * </ol>
103  * </li>
104  * <li>Cloning. Where you need an object to be safe, you clone it.</li>
105  * </ol>
106  * <p>
107  * There are advantages and disadvantages of each of these.
108  * </p>
109  * <ol>
110  * <li>Const provides a certain level of protection, but since const can be and
111  * is often cast away, it only protects against most inadvertent mistakes. It
112  * also offers no threading protection, since anyone who has a pointer to the
113  * (unconst) object in another thread can mess you up.</li>
114  * <li>Immutable wrappers are safer than const in that the constness can't be
115  * cast away. But other than that they have all the same problems: not safe if
116  * someone else keeps hold of the original object, or if any of the objects
117  * returned by the class are mutable.</li>
118  * <li>Always-Immutable Objects are safe, but usage can require excessive
119  * object creation.</li>
120  * <li>Cloning is only safe if the object truly has a 'safe' clone; defined as
121  * one that <i>ensures that no change to the clone affects the original</i>.
122  * Unfortunately, many objects don't have a 'safe' clone, and always cloning can
123  * require excessive object creation.</li>
124  * </ol>
125  * <h2>Freezable Model</h2>
126  * <p>
127  * The <code>Freezable</code> model supplements these choices by giving you
128  * the ability to build up an object by calling various methods, then when it is
129  * in a final state, you can <i>make</i> it immutable. Once immutable, an
130  * object cannot <i>ever </i>be modified, and is completely thread-safe: that
131  * is, multiple threads can have references to it without any synchronization.
132  * If someone needs a mutable version of an object, they can use
133  * <code>cloneAsThawed()</code>, and modify the copy. This provides a simple,
134  * effective mechanism for safe classes in circumstances where the alternatives
135  * are insufficient or clumsy. (If an object is shared before it is immutable,
136  * then it is the responsibility of each thread to mutex its usage (as with
137  * other objects).)
138  * </p>
139  * <p>
140  * Here is what needs to be done to implement this interface, depending on the
141  * type of the object.
142  * </p>
143  * <h3><b>Immutable Objects</b></h3>
144  * <p>
145  * These are the easiest. You just use the interface to reflect that, by adding
146  * the following:
147  * </p>
148  *
149  * <pre>
150  * public class A implements Freezable {
151  * ...
152  * public final boolean isFrozen() {return true;}
153  * public final Object freeze() {return this;}
154  * public final Object cloneAsThawed() { return this; }
155  * }
156  * </pre>
157  *
158  * <p>
159  * These can be final methods because subclasses of immutable objects must
160  * themselves be immutable. (Note: <code>freeze</code> is returning
161  * <code>this</code> for chaining.)
162  * </p>
163  * <h3><b>Mutable Objects</b></h3>
164  * <p>
165  * Add a protected 'flagging' field:
166  * </p>
167  *
168  * <pre>
169  * protected boolean immutable;
170  * </pre>
171  *
172  * <p>
173  * Add the following methods:
174  * </p>
175  *
176  * <pre>
177  * public final boolean isFrozen() {
178  * return frozen;
179  * };
180  *
181  * public Object freeze() {
182  * frozen = true;
183  * return this;
184  * }
185  * </pre>
186  *
187  * <p>
188  * Add a <code>cloneAsThawed()</code> method following the normal pattern for
189  * <code>clone()</code>, except that <code>frozen=false</code> in the new
190  * clone.
191  * </p>
192  * <p>
193  * Then take the setters (that is, any method that can change the internal state
194  * of the object), and add the following as the first statement:
195  * </p>
196  *
197  * <pre>
198  * if (isFrozen()) {
199  * throw new UnsupportedOperationException(&quot;Attempt to modify frozen object&quot;);
200  * }
201  * </pre>
202  *
203  * <h4><b>Subclassing</b></h4>
204  * <p>
205  * Any subclass of a <code>Freezable</code> will just use its superclass's
206  * flagging field. It must override <code>freeze()</code> and
207  * <code>cloneAsThawed()</code> to call the superclass, but normally does not
208  * override <code>isFrozen()</code>. It must then just pay attention to its
209  * own getters, setters and fields.
210  * </p>
211  * <h4><b>Internal Caches</b></h4>
212  * <p>
213  * Internal caches are cases where the object is logically unmodified, but
214  * internal state of the object changes. For example, there are const C++
215  * functions that cast away the const on the &quot;this&quot; pointer in order
216  * to modify an object cache. These cases are handled by mutexing the internal
217  * cache to ensure thread-safety. For example, suppose that UnicodeSet had an
218  * internal marker to the last code point accessed. In this case, the field is
219  * not externally visible, so the only thing you need to do is to synchronize
220  * the field for thread safety.
221  * </p>
222  * <h4>Unsafe Internal Access</h4>
223  * <p>
224  * Internal fields are called <i>safe</i> if they are either
225  * <code>frozen</code> or immutable (such as String or primitives). If you've
226  * never allowed internal access to these, then you are all done. For example,
227  * converting UnicodeSet to be <code>Freezable</code> is just accomplished
228  * with the above steps. But remember that you <i><b>have</b></i> allowed
229  * access to unsafe internals if you have any code like the following, in a
230  * getter, setter, or constructor:
231  * </p>
232  *
233  * <pre>
234  * Collection getStuff() {
235  * return stuff;
236  * } // caller could keep reference &amp; modify
237  *
238  * void setStuff(Collection x) {
239  * stuff = x;
240  * } // caller could keep reference &amp; modify
241  *
242  * MyClass(Collection x) {
243  * stuff = x;
244  * } // caller could keep reference &amp; modify
245  * </pre>
246  *
247  * <p>
248  * These also illustrated in the code sample in <b>Background</b> above.
249  * </p>
250  * <p>
251  * To deal with unsafe internals, the simplest course of action is to do the
252  * work in the <code>
253  freeze()</code> function. Just make all of your internal
254  * fields frozen, and set the frozen flag. Any subsequent getter/setter will
255  * work properly. Here is an example:
256  * </p>
257  *
258  * <pre>
259  * public Object freeze() {
260  * if (!frozen) {
261  * foo.freeze();
262  * frozen = true;
263  * }
264  * return this;
265  * }
266  * </pre>
267  *
268  * <p>
269  * If the field is a <code>Collection</code> or <code>Map</code>, then to
270  * make it frozen you have two choices. If you have never allowed access to the
271  * collection from outside your object, then just wrap it to prevent future
272  * modification.
273  * </p>
274  *
275  * <pre>
276  * zone_to_country = Collections.unmodifiableMap(zone_to_country);
277  * </pre>
278  *
279  * <p>
280  * If you have <i>ever</i> allowed access, then do a <code>clone()</code>
281  * before wrapping it.
282  * </p>
283  *
284  * <pre>
285  * zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());
286  * </pre>
287  *
288  * <p>
289  * If a collection <i>(or any other container of objects)</i> itself can
290  * contain mutable objects, then for a safe clone you need to recurse through it
291  * to make the entire collection immutable. The recursing code should pick the
292  * most specific collection available, to avoid the necessity of later
293  * downcasing.
294  * </p>
295  * <blockquote>
296  * <p>
297  * <b>Note: </b>An annoying flaw in Java is that the generic collections, like
298  * <code>Map</code> or <code>Set</code>, don't have a <code>clone()</code>
299  * operation. When you don't know the type of the collection, the simplest
300  * course is to just create a new collection:
301  * </p>
302  *
303  * <pre>
304  * zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));
305  * </pre>
306  *
307  * </blockquote>
308  *
309  * @internal revisit for ICU 3.6
310  * @deprecated This API is ICU internal only.
311  */

312 public interface Freezable extends Cloneable JavaDoc {
313     /**
314      * Determines whether the object has been locked or not.
315      * @internal revisit for ICU 3.6
316      * @deprecated This API is ICU internal only.
317      */

318     public boolean isFrozen();
319
320     /**
321      * Locks the object.
322      * @return the object itself.
323      * @internal revisit for ICU 3.6
324      * @deprecated This API is ICU internal only.
325      */

326     public Object JavaDoc freeze();
327
328     /**
329      * Provides for the clone operation. Any clone is initially unlocked.
330      * @internal revisit for ICU 3.6
331      * @deprecated This API is ICU internal only.
332      */

333     public Object JavaDoc cloneAsThawed();
334 }
335
Popular Tags