Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Make your apps fly

Implement Flyweight to improve performance

  • Print
  • Feedback

Page 2 of 5

Figure 2's sequence diagram depicts runtime interaction between clients and a flyweight factory.

Figure 2. Flyweight sequence diagram

Clients don't directly instantiate flyweights; instead they get them from a factory. The factory first checks to see if it has a flyweight that fits specific criteria (e.g., a blue or white line); if so, the factory returns a reference to the flyweight. If the factory can't locate a flyweight for the specified criteria, it instantiates one, adds it to the pool, and returns it to the client.

You might be wondering how you can reuse flyweights. For example, how can one line flyweight draw all lines of a particular color when those lines presumably have different locations and lengths? You accomplish that reuse by splitting a flyweight's state in two: intrinsic state (e.g., line color) and extrinsic state (e.g., line location and length). The flyweight maintains intrinsic state, while extrinsic state must be passed to the flyweight at runtime. By externalizing extrinsic state, you can easily reuse flyweights for different variations of that extrinsic state.

Flyweights are abundant in Java, from simple strings to Swing tree nodes and component borders. The rest of this article discusses those flyweights and concludes with an example of how you can implement your own flyweights.

Java strings

Because strings are usually plentiful in most applications, Java goes to great lengths to make sure strings perform well. First, strings are immutable, so they don't have to be thread-safe. Because synchronization is expensive, strings are spared that drag on performance. Second, as you might guess, strings specified at compile-time are flyweights—strings that contain the same character sequence are shared. That sharing can greatly reduce memory footprints, and therefore, increase performance.

Example 1's application demonstrates Java strings' flyweight nature.

Example 1. Flyweight strings

public class StringTest {
   public static void main(String[] args) {
      String fly = "fly", weight = "weight";
      String fly2 = "fly", weight2 = "weight"; 
      System.out.println(fly == fly2);       // fly and fly2 refer to the same String instance
      System.out.println(weight == weight2); // weight and weight2 also refer to
                                             // the same String instance
      String distinctString = fly + weight;
      System.out.println(distinctString == "flyweight"); // flyweight and "flyweight" do not
                                                         // refer to the same instance
      String flyweight = (fly + weight).intern();
      System.out.println(flyweight == "flyweight"); // The intern() method returns a flyweight
   }
}


Here's the application's output: true true false true.

In the preceding application, the strings fly and fly2 refer to the same string object (recall that the == operator evaluates to true if the objects it compares are the same). Ditto for weight and weight2.

Strings computed at runtime, such as distinctString in the preceding application, are not flyweights by default; however, you can force the issue with the String.intern() method—a poorly named method that brings to mind medical topics, but nonetheless returns flyweights for strings computed at runtime.

  • Print
  • Feedback

Resources