Flyweight Pattern Tutorial with Java Examples
Learn the Flyweight Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
Join the DZone community and get the full member experience.
Join For FreeToday'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. Thedefinition of Flyweight provided in the original Gang of Four book on DesignPatterns 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
//Flyweightpublic interface LineFlyweight{public Color getColor();public void draw(Point location);}
The line will implement this interface:
//ConcreteFlyweightpublic 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 factorypublic 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 poolLineFlyweight 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 independentlyline.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.
Next Up
Next week, we'll be taking a look at the Bridge pattern.
Enjoy the Whole "Design Patterns Uncovered" Series:
Creational Patterns
- Learn The Abstract Factory Pattern
- Learn The Builder Pattern
- Learn The Factory Method Pattern
- Learn The Prototype Pattern
- Learn The Singleton Pattern
Structural Patterns
- Learn The Adapter Pattern
- Learn The Bridge Pattern
- Learn The Composite Pattern
- Learn The Decorator Pattern
- Learn The Facade Pattern
- Learn The Flyweight Pattern
- Learn The Proxy Pattern
Behavioral Patterns
- Learn The Chain of Responsibility Pattern
- Learn The Command Pattern
- Learn The Interpreter Pattern
- Learn The Iterator Pattern
- Learn The Mediator Pattern
- Learn The Memento Pattern
- Learn The Observer Pattern
- Learn The State Pattern
- Learn The Strategy Pattern
- Learn The Template Method Pattern
- Learn The Visitor Pattern
Opinions expressed by DZone contributors are their own.
Comments