22

I have been studying design patterns and came accross the fly weight pattern. I have been trying to see opportunities to use the pattern in my applications but I am having trouble seeing how to use it. Also, what are some signs that a fly weight pattern is being used when I read other peoples code?

According to the definition it says:

Use sharing to support large numbers of fine-grained objects efficiently.

If I read it right Dictionaries and Hashtables could be instances of fly weights is this correct?

Thanks in advance.

6
  • 7
    Just a little anecdote on flyweights: I once had to create large excel files (up to 500k records, over 100 columns) with a 3rd party API. The styles for the cells became extremely memory intensive. So whenever a style was needed, a hashtable was checked if an equal style already existed and then provided just a reference to this style. This modification made this export possible. Now having that much data in excel is madness in my opinion. But the controllers had their analysis macros which they wanted to keep.
    – Falcon
    Sep 15, 2011 at 20:49
  • 9
    Comment: I hope that people who write pattern and OO books and articles come to the real world of the average programmer and stop using lawyer style English!
    – NoChance
    Sep 15, 2011 at 22:17
  • 1
    "I once had to create large excel files (up to 500k records, over 100 columns)" -- that's not much compared to what some traders are capable of creating ;-)
    – quant_dev
    Sep 15, 2011 at 22:38
  • After reading several of these examples I would think in memory data compression would be an execellent place to implement this technique. Thanks for the help!
    – Jeremy E
    Sep 16, 2011 at 13:22
  • Table cells in GWT are flyweights.
    – user16764
    Nov 29, 2013 at 6:00

4 Answers 4

21

One example is in the Java libraries. Java has primitive types (e.g. int, which is a 32-bit integer) and wrappers for them (e.g. Integer, which wraps int). There are methods to "box" an int into an Integer and unbox an Integer into an int. The wrappers are necessary because the primitive types aren't objects and hence can't e.g. be used as keys in Maps or placed in Collections.

The boxing method uses an array of flyweight objects as a kind of cache for Integers corresponding to int values between -128 and 127. Since those are the values most likely to be used as keys or placed in collections, it reduces allocation and memory use. (If there are 5000000 Integers representing the value 0 floating around, that uses 5000000 times as much memory as reusing the flyweight instance).

4
  • 3
    stackoverflow.com/questions/2909848/… :)
    – Oded
    Sep 15, 2011 at 20:44
  • 1
    So the intern pool for strings in C# is another example of the flyweight pattern correct?
    – Jeremy E
    Sep 15, 2011 at 20:47
  • 1
    @Jeremy E: Yes, in my opinion you can call string interning an application of the flyweight pattern, altough for strings, it's not only about memory consumption, but also about runtime efficiency.
    – Falcon
    Sep 15, 2011 at 20:57
  • Objective-C tagged pointers take this to an extreme. Boxed integers up to 56 bits, and many strings up to six characters, are not even allocated as objects, but all the information is packed into the object pointer itself.
    – gnasher729
    Apr 12, 2017 at 19:29
9

Graphics. Typically, a raster image (which are the backbone of most consumer-level computer graphics) is CPU-cheap, but memory-expensive to work with (which is fine because memory's cheap but CPU is expensive). If that raster image is to be repeated many times in rendering a larger UI (from icons in a Windows GUI app to characters of a font in a word processor, to textures on surfaces in a 3D game), it makes a lot of sense to load the image into memory once, and simply point to it using very simple objects that are cheap to make and do not, themselves, take up a lot of memory. A sprite, which is simply a point in graphical space at which an image should be displayed, is just a 3D point and a memory pointer to the first pixel of the image to use. MAYBE it also includes the dimensions of the portion of the sprite image file to be used, either in graphical or memory terms. This information is all very inexpensive to change, say to change the image or location of the sprite, and it can be done without loading a new image each time, thus drastically increasing performance of the underlying program to manipulate and display the proper portions of the proper images to render a complete UI "scene".

4

The purpose on using the flyweight pattern is to avoid unnecessary object initialization and thus save space. As defined by GOF, an object can have two states, the intrinsic and the extrinsic state:

  • Intrinsic state: Is stored in the flyweight; it consists of information that's independent on the flyweights context, thereby making it shareable.
  • Extrinsic state: depends on and varies with the flyweight's context and therefore cant be share. Client objects are responsible for passing extrinsic state to the flyweight when it needs it.

Assuming that we want to develop a simple text editor application where each column contains all the rows of the text and the row can contain characters.

The dilemma here is how to design the Character class. The char c within the Character class should be the main (intrinsic state) object. However, a char can have a Font and and Size (extrinsic state); thus we need to store its extrinsic state on the Row (client) and access it when needed. For this purpose, two lists which store the Fonts and the Sizes are created.

By following the Flyweight pattern, the Character is now reusable and the objects are being referenced from a specific list of objects (the flyweight pool) which contains all the ASCII symbols (Character objects).

Here is what I described visually:

enter image description here

For printing 'hello', only 4 Character objects are needed, instead of 5. Once the font is changed, no new objects are required; note that this would not be possible had we stored the extrinsic state on the Character class, e.g.,

class Character
{
    char c;
    int Size;
    Font font;

    ....
}

Applying this pattern on large datasets would lead to significant optimizations on the memory complexity of the application and object reusability.

0
3

ASCII-range Character instances in Smalltalk are flyweights.

When you evaluate something like Character space, Character class >> #value: executes:

value: anInteger 
    "Answer the Character whose value is anInteger."

    anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
    ^ CharacterTable at: anInteger + 1.

The class variable CharacterTable is initialised like this:

initialize
    "Create the table of unique Characters, and DigitsValues."
    "Character initializeClassificationTable"

    CharacterTable ifNil: [
        "Initialize only once to ensure that byte characters are unique"
        CharacterTable := Array new: 256.
        1 to: 256 do: [:i | CharacterTable
            at: i
            put: (self basicNew setValue: i - 1)]].
    self initializeDigitValues

So when you create a String, the ASCII-range Characters will come from CharacterTable rather than being newly-created every time.

Not the answer you're looking for? Browse other questions tagged or ask your own question.