I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Design Patterns Uncovered: The Flyweight Pattern

05.19.2010
| 34241 views |
  • submit to reddit

Today's pattern is the Flyweight pattern, used to share large number of objects in an efficient way.

Flyweight in the Real World 

The classic example of the Flyweight pattern is the representation of a character in a word processor. Rather than each character having seperate glyph objects that represent the font and formatting data, each character could have a reference to a flyweight glyph object shared by every instance of the same cahracter in the document. In this case, the character need only store it's position in the the document, rather than it's entire formatting information.

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone's Design Patterns Refcard is the best place to start. 

The Flyweight Pattern

Flyweight is known as a structural pattern, as it's used to form large object structures across many disparate objects. The definition of Flyweight provided in the original Gang of Four book on Design Patterns states: 

Facilitates the reuse of many fine grained objects, making the utilization of large numbers of objects more efficient.

When considering this pattern, you will need to think about intrinsic and extrinsic data. Intrinsic data is the data that makes this object instance unique. Meanwhile, extrinsic data is information that can be passed in through arguments. So, if you can make some data extrinsic for cases that you have a large number of objects, the Flyweight pattern may be exactly what you are looking for. 

The Flyweight interface declares methods which flyweight instances can receive and use extrinsic data. The FlyweightFactory is responsible for the creation and management of the flyweights, ensuring that they are shared properly. If the desired Flyweight isn't created yet it will create and return one. Otherwise, it will return one from the current pool of flyweights. 

ConcreteFlyweight adds capabilities for intrinsic state. This flyweight object must be sharable. The UnsharedConcreteFlyweight provides a way to use this pattern without enforcing the shared concept the the interface encourages. However, most uses of this pattern involve sharable flyweights.

Would I Use This Pattern?

This pattern should be used when: 

  • Many similar objects are used and the storage cost is high
  • The majority of each object's state data can be made extrinsic
  • A few shared objects would easily replace many unshared objects
  • The identity of each object does not matter
The typical case for this pattern is with system resources, as mentioned in our real world example. Icons or folders are good candidates for use of this pattern. 

So How Does It Work In Java?

Let's use drawing lines of different colors as an example here. We want to avoid creating a new line for each color, instead choosing to reuse lines with the same color. 

First, we'll create an interface for our flyweights. The draw method provides the extrinsic data of where to draw the line

//Flyweight
public interface LineFlyweight
{
public Color getColor();
public void draw(Point location);
}

The line will implement this interface: 

//ConcreteFlyweight
public class Line implements LineFlyweight
{
private Color color;

public Line(Color c)
{
color = c;
}

public Color getColor()
{
return color;
}

public void draw(Point location)
{
//draw the character on screen
}

}

Our factory will manage the creation of the line objects: 


//Flyweight factory
public class LineFlyweightFactory
{
private List<LineFlyweight> pool;

public LineFlyweightFactory()
{
pool = new ArrayList<LineFlyweight>();
}

public LineFlyweight getLine(Color c)
{
//check if we've already created a line with this color
for(LineFlyweight line: pool)
{
if(line.getColor().equals(c))
{
return line;
}
}
//if not, create one and save it to the pool
LineFlyweight line = new Line(c);
pool.add(line);
return line;
}

}

When the client wants to create a line, they can just use the factory as follows: 

LineFlyweightFactory factory = new LineFlyweightFactory(); 
....
LineFlyweight line = factory.getLine(Color.RED);
LineFlyweight line2 = factory.getLine(Color.RED);

//can use the lines independently
line.draw(new Point(100, 100));
line2.draw(new Point(200, 100));

Watch Out for the Downsides

One of the drawbacks of this pattern is that all instances of the class are related, so single instances of the class will not be able to behave independently from other instances.

Other Articles in This Series
The Observer Pattern
The Adapter Pattern
The Facade Pattern
The Factory Method Pattern
The Abstract Factory Pattern
The Singleton Pattern
The Strategy Pattern
The Visitor Pattern

The Decorator Pattern
The Proxy Pattern
The Command Pattern
The Chain of Responsibility Pattern
The Interpreter Pattern
The Composite Pattern

Next Up

Next week, we'll be taking a look at the Bridge pattern.
Tags:

Comments

Straub Edwin replied on Wed, 2010/05/26 - 3:05am

Hi James,

   Nice series of articles on design patterns. But shouldn't the getFlyweight(key) method in the FlyweightFactory return a FlyWeight (interface) object ?

Alexander Orlov replied on Mon, 2014/05/26 - 5:41pm

Abstract interface method do not need to be public (overdeterminism). Every interface method is public by definition.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.