Design Patterns Uncovered: The Flyweight Pattern
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
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.(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





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 ?