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