September 2, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working with Design Patterns: Flyweight

  • May 14, 2007
  • By Jeff Langr
  • Send Email »
  • More Articles »

Now that I've encapsulated instantiation in the factory's create method, I can control when Time objects get created. As the first step, I create a unique key by concatenating the hour and the minute into a time string. I use this key to extract an entry, if one exists, from a new HashMap named times. If an entry exists, I return it. If no entry exists, I create a new Time object, and stuff it into the times map at the key I created.

That's it. Implementing flyweight can be this straightforward. The chief downsides are:

  • Instantiation of all Time objects must be done through the factory. If not, you lose the benefit of flyweight.
  • Using the factory requires the overhead of an additional method call and a hash table lookup. This rarely presents a performance problem in Java.

So, was it worth it? I hacked together a quick application class to see whether the flyweight was paying off:

import java.util.*;

public class App extends Thread {
   private static Random random = new Random();

   public static void main(String[] args) {
      new App().start();
   }

   public void run() {
      int size = 1000000;
      List<Appointment> appointments =
         new ArrayList<Appointment>(size);
      for (int i = 0; i < size; i++) {
         appointments.add(createRandomAppt());
      }
      System.out.println("created " + appointments.size());
      while (true) {
         Thread.yield();
      }
   }

   private Appointment createRandomAppt() {
      Time start = createRandomTime();
      Time stop = createRandomTime();   // kind of bogus
      return new Appointment(start, stop);
   }

   private Time createRandomTime() {
      byte hour = (byte)random.nextInt(24);
      byte quartile = (byte)random.nextInt(4);
      byte minute = 0;
      switch (quartile) {
         case 0:
            minute = 0;
            break;
         case 1:
            minute = 15;
            break;
         case 2:
            minute = 30;
            break;
         case 3:
            minute = 45;
            break;
      }
      //return new Time(hour, minute);
      return TimeFactory.create(hour, minute);
   }
}

Ignoring the fact that an appointment stop time probably should be some time later than its start time, the application puts together a number of appointments with random stop and start times. The times are constrained to quarter-hour marks. This is good enough for a quick test; in reality, appointment times during a typical business day are likely to be even more constrained.

The last two lines in createRandomTime control how the Time instances get created. For the first run, I uncommented the line that creates a Time directly via its constructor:

   return new Time(hour, minute);

and commented out the line that uses the factory.

I ran jconsole (which ships as part of Java 5 and 6) to monitor the application. Heap profiling indicated that the application required between 52 and 56 million bytes.

Finally, I switched how Time objects got created, uncommenting the line that uses the factory:

   return TimeFactory.create(hour, minute);

The second run of jconsole showed that the application now took between 20 and 22 million bytes. In this case, using the flyweight pattern has saved me over 30 million bytes!

As with any memory or performance optimization, profiling and tests are essential. It's easy to optimize the wrong thing, or even to introduce defects during optimization. Used properly, patterns such as flyweight can quickly provide your application with significant improvement in memory usage.

About the Author

Jeff Langr is a veteran software developer with a score and more years of experience. He's authored two books and dozens of published articles on software development, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him directly at jeff@langrsoft.com.



Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel