Flyweight Design Pattern

Flyweight is used when there is a need to create high number of objects of almost similar nature. High number of objects consumes high memory and flyweight design pattern gives a solution to reduce the load on memory by sharing objects. It is achieved by segregating object properties into two types intrinsic and extrinsic. In this article lets see about this in detail with a real world example and respective java implementation.

Intent as stated by GoF is, “Use sharing to support large numbers of fine-grained objects efficiently”. Sharing is key in flyweight pattern and we need to judiciously decide if this pattern can be applied.

When to Use Flyweight Design Pattern

We need to consider following factors when choosing flyweight,

Flyweight is all about memory and sharing. Nowadays an average desktop comes with 500 GB hard disk, 4GB ram and with this you can stuff your whole home inside and will still have remaining space to put an elephant in it. Do we really need to bother about memory and usage? Since the cost has come down there is no restriction to use it effectively. Think about mobile devices that are increasing everyday and they still have memory constraint.

Even if you have huge memory, in some cases the application may need efficient use of it. For example assume we are working with an application that maps stars from universe. In this application if we are going to create an object for every star then think of it how much memory we will need. Gang of Four (GoF) have given an example of text editors in their book. If we create an object for every character in a file, think of it how many objects we will create for a long document. What will be the application performance.

How to Apply Flyweight

The object which we are going to create in high number should be analyzed before going for flyweight. Idea is to create lesser number of objects by reusing the same objects. Create smaller groups of objects and they should be reused by sharing. Closely look at objects properties and they can be segregated as two types intrinsic and extrinsic. Sharing is judged with respect to a context. Lets take the example of editors.


Consider a simple text editor where we can use only alphabet set A to Z. If we are going to create 100 page document using this editor we may have 200000 (2000 X 100) characters (assuming 2000 characters / page). Without flyweight we will create 200000 objects to have fine grained control. With such fine control, every character can have its own characteristics like color, font, size, etc. How do we apply flyweight here?

Intrinsic and Extrinsic State

Create only 26 objects for (A to Z) mapping every unique characters. These 26 objects will have intrinsic state as its character. That is object ‘a’ will have state as character ‘a’. Then what happens to color, font and size? Those are the extrinsic state and will be passed by client code. 26 objects will be in store, client code will get the needed character/object and pass the extrinsic state to it with respect to the context. With respect to context means, ‘a’ in first line may come in red color and the same character may come in blue color in different line.

Flyweight Implementation

The object with intrinsic state is called flyweight object. When we implement flyweight we create concrete objects and have the intrinsic state stored in that. To create those concrete objects we will have factory and that is called Flyweight factory. This factory is to ensure that the objects are shared and we don’t end up creating duplicate objects.

Let us take an example scenario of drawing. We need to draw different geometrical shapes like rectangles and ovals in huge number. Every shape may vary in colour, size, fill type, font used. For implementation sake lets limit our shapes to two rectangle and oval. Every shape will be accompanied by a label which directly maps it with the shape. That is all rectangles will have label as ‘R’ and all ovals will have label as ‘O’.

Now our flyweight will have intrinsic state as label only. Therefore we will have only two flyweight objects. The varying properties colour, size, fill type and font will be extrinsic. We will have a flyweight factory that will maintain the two flyweight objects and distribute to client accordingly. There will be an interface for the flyweights to implement so that we will have a common blueprint and that is the flyweight interface.

Client code will use random number generators to create extrinsic properties. We are not storing the extrinsic properties anywhere, we will calculate on the fly and pass it. Use of random number generator is for convenience.

UML for Flyweight

Java Code Implementation for Flyweight

package com.javapapers.designpattern.flyweight;

import java.awt.Color;
import java.awt.Graphics;

public interface MyShape {
	public void draw(Graphics g, int x, int y, int width, int height,
			Color color, boolean fill, String font);
}

 

package com.javapapers.designpattern.flyweight;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

public class MyOval implements MyShape {

	private String label;

	public MyOval(String label) {
		this.label = label;

	}

	public void draw(Graphics oval, int x, int y, int width, int height,
			Color color, boolean fill, String font) {
		oval.setColor(color);
		oval.drawOval(x, y, width, height);
		oval.setFont(new Font(font, 12, 12));
		oval.drawString(label, x + (width / 2), y);
		if (fill)
			oval.fillOval(x, y, width, height);
	}
}

 

package com.javapapers.designpattern.flyweight;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

public class MyRectangle implements MyShape {

	private String label;

	public MyRectangle(String label) {
		this.label = label;

	}

	public void draw(Graphics rectangle, int x, int y, int width, int height,
			Color color, boolean fill, String font) {
		rectangle.setColor(color);
		rectangle.drawRect(x, y, width, height);
		rectangle.setFont(new Font(font, 12, 12));
		rectangle.drawString(label, x + (width / 2), y);
		if (fill)
			rectangle.fillRect(x, y, width, height);
	}
}

 

package com.javapapers.designpattern.flyweight;

import java.util.HashMap;

public class ShapeFactory {

	private static final HashMap shapes = new HashMap();

	public static MyShape getShape(String label) {
		MyShape concreteShape = (MyShape) shapes.get(label);

		if (concreteShape == null) {
			if (label.equals("R")) {
				concreteShape = new MyRectangle(label);
			} else if (label.equals("O")) {
				concreteShape = new MyOval(label);
			}
			shapes.put(label, concreteShape);
		}
		return concreteShape;
	}
}

 

package com.javapapers.designpattern.flyweight;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Client extends JFrame {

	private static final int WIDTH = 400;
	private static final int HEIGHT = 400;

	private static final String shapes[] = { "R", "O" };
	private static final Color colors[] = { Color.red, Color.green, Color.blue };
	private static final boolean fill[] = { true, false };
	private static final String font[] = { "Arial", "Courier" };

	public Client() {
		Container contentPane = getContentPane();

		JButton startButton = new JButton("Draw Shapes");
		final JPanel panel = new JPanel();

		contentPane.add(panel, BorderLayout.CENTER);
		contentPane.add(startButton, BorderLayout.SOUTH);
		setSize(WIDTH, WIDTH);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);

		startButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				Graphics g = panel.getGraphics();
				for (int i = 0; i < 100; ++i) {
					MyShape shape = ShapeFactory.getShape(getRandomShape());
					shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
							getRandomHeight(), getRandomColor(),
							getRandomFill(), getRandomFont());
				}
			}
		});
	}

	private String getRandomShape() {
		return shapes[(int) (Math.random() * shapes.length)];
	}

	private int getRandomX() {
		return (int) (Math.random() * WIDTH);
	}

	private int getRandomY() {
		return (int) (Math.random() * HEIGHT);
	}

	private int getRandomWidth() {
		return (int) (Math.random() * (WIDTH / 7));
	}

	private int getRandomHeight() {
		return (int) (Math.random() * (HEIGHT / 7));
	}

	private Color getRandomColor() {
		return colors[(int) (Math.random() * colors.length)];
	}

	private boolean getRandomFill() {
		return fill[(int) (Math.random() * fill.length)];
	}

	private String getRandomFont() {
		return font[(int) (Math.random() * font.length)];
	}

	public static void main(String[] args) {
		Client client = new Client();
	}
}

Download Flyweight Java Source Code

Flyweight Implementation Output

Use of Flyweight in JDK

java.lang.Integer#valueOf(int) (also on Boolean, Byte, Character, Short, Long, Float and Double). API doc says, "...this method is likely to yield significantly better space and time performance by caching frequently requested values....".

Design Pattern Related to Flyweight

Factory design pattern and singleton design pattern is used in implementing the flyweight.

This Design Patterns tutorial was added on 24/06/2012.

Comments on "Flyweight Design Pattern" Tutorial:

  1. Sharil says:

    Please Explain DAO factory and Transfer Object design pattern

  2. Sindhu says:

    Thanks a lot for explaining a tougher topic in simple..

  3. Sivasubramaniam Arunachalam says:

    String interning also works in the same way?

  4. Kapil Suryawanshi says:

    Thank you, this is very clear.

  5. Sandy says:

    design made easy, you make it so simple to understand

  6. Rani says:

    This material is excellent. I have tried studying multiple times but ended up with understanding nothing. This is very clear n simple. Hats off to your dedication.

  7. Shivmani says:

    This is like spoon feeding to developer . Handled subject with idealistic theory .
    Expecting some more posts.. :)

  8. sandeep says:

    its very nice

  9. Ishtiaque Hussain says:

    Thank you for the article. I am just introduced to a new Design Pattern

  10. sriharsha says:

    thanks a lot. you are making some tough topics look very simple with your articles.

  11. Hiral says:

    Really very interesting and memory efficient topic!! Keep going!!!

  12. Pranay Jain says:

    Nice explanation

  13. Ramani says:

    Nice article, but I am not able to find any difference between this pattern and Factory Method Design pattern. Can someone clarify?

  14. Vijayakumar says:

    Good effort and thanks to Joe. Is this applied in Spring container since it is responsible for loading all the object during initialization?

  15. surya says:

    plz exmplain DAO factorys

  16. Anonymous says:

    Simple and Elegant!

  17. Navneet says:

    What a nice explanation Joe. Thank you very much

  18. chandan kumar says:

    gr8 joe , what a nice article you are posting..man……

  19. Anonymous says:

    Thank you so much for the crystal clear explanation, waiting for your articles on behavioral design patterns

  20. Nirav Shah says:

    Very good tutorial…very well explained…Thanks

  21. S.D says:

    Good one to learn term design pattern who really confused regarding it.

  22. Anonymous says:

    when we can expect Behavioral Design Patterns

  23. DC says:

    when we can expect Behavioral Design Patterns

  24. Dip says:

    Behavioral Design Patterns?

  25. Murali says:

    Nice Joe, great one keep doing …….

  26. Mathiazhagan says:

    I need some more example plz..!

  27. Kalpesh says:

    Very good explanation

  28. Venkatagiri Vatlam says:

    This is an excellent article Joe, keep up the good work. Your example is awesome. This only tempts any developer to know all the design patterns in this fashion..

  29. Amit says:

    This is amazing man!!
    I have become fan of this blog.
    Btw, Are you sure DOuble class uses this ValueOf method as cache like Integer does?
    Source code does not have it.
    Please clarify.
    Thanks Again!!!

  30. mars@Marikannan says:

    Hi Joe, Excellent explanation about Design pattern i am very happy to learn. But i expect to complete Behavioral Design Patterns Kindly we request post your words asap.

    Thanks

  31. srinivas says:

    I LIKE TO SHARE BOUT THE BLOG TO MY BUDDIES
    This blog made me to know more about design patterns

    THANKS

  32. Viswa says:

    Where is the singleton used here ?

  33. Anonymous says:

    Even Websphere Portal internally uses Flyweight pattern and was easily understood internally by reading this blog. Great work !!!!!!

    Thanks,
    Subba.

  34. Lindon says:

    While the explanation is excellent, the example seems to have missed showing that flyweight is useful when you have to create large number of objects. Rather, what the example is showing is that two objects whose draw method is called large number of times. Sure, each time it is called, a shape “object” is produced, but that’s not the “Java object” that the pattern is about.

  35. Eswar says:

    very nice and simple presentation

  36. Javier says:

    Hello ! I’m studyng this design pattern and the info provided is great, but… it would be great if you could write a little example using a ‘UnsharedConcreteFlyweight’ class (I can’t understand the explanation in the GoF’s book)

    Thanks !

  37. Javier says:

    Ah, one question… as I understand this design pattern can only be used for ‘one use objects’ ?

    I mean, if I draw 10 squares I could not access or select one of them to change its color, for example…

  38. K SHIRIN BHANU says:

    Thanks a lot for your explanation.
    Its very easy to understand

  39. Anonymous says:

    Excellant explantion

  40. Abhijit says:

    Joe,

    Hat off to you! realy nice explanation with lucid language.
    I have below question

    can we say that pool of database connection is an example of Flyweight Design Pattern?

  41. arik says:

    That was so easy explanation to a tough topic. Keep writing and help others to gain knowledge.

    Thanks again.

  42. Ravi says:

    Yes. It does. Infact String Intern is an implementation of Fly-Weight DP.

  43. arc says:

    Your explanation was very helpful. I was having trouble understanding it from Eckel’s book and then from Wikipedia. Thanks :).

  44. sadun says:

    thank you, it is very helpfull.

  45. Dinesh says:

    Thanks a lot, its very much helpful.

Comments are closed for this "Flyweight Design Pattern" tutorial.