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.
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.
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?
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.
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.
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
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....".
Factory design pattern and singleton design pattern is used in implementing the flyweight.
Comments are closed for "Flyweight Design Pattern".
Please Explain DAO factory and Transfer Object design pattern
Thanks a lot for explaining a tougher topic in simple..
String interning also works in the same way?
Thank you, this is very clear.
design made easy, you make it so simple to understand
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.
This is like spoon feeding to developer . Handled subject with idealistic theory .
Expecting some more posts.. :)
its very nice
Thank you for the article. I am just introduced to a new Design Pattern
thanks a lot. you are making some tough topics look very simple with your articles.
Really very interesting and memory efficient topic!! Keep going!!!
Nice explanation
Nice article, but I am not able to find any difference between this pattern and Factory Method Design pattern. Can someone clarify?
Good effort and thanks to Joe. Is this applied in Spring container since it is responsible for loading all the object during initialization?
plz exmplain DAO factorys
Simple and Elegant!
What a nice explanation Joe. Thank you very much
gr8 joe , what a nice article you are posting..man……
Thank you so much for the crystal clear explanation, waiting for your articles on behavioral design patterns
Very good tutorial…very well explained…Thanks
Good one to learn term design pattern who really confused regarding it.
when we can expect Behavioral Design Patterns
when we can expect Behavioral Design Patterns
Behavioral Design Patterns?
Nice Joe, great one keep doing …….
I need some more example plz..!
Very good explanation
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..
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!!!
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
I LIKE TO SHARE BOUT THE BLOG TO MY BUDDIES
This blog made me to know more about design patterns
THANKS
Where is the singleton used here ?
Even Websphere Portal internally uses Flyweight pattern and was easily understood internally by reading this blog. Great work !!!!!!
Thanks,
Subba.
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.
very nice and simple presentation
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 !
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…
Thanks a lot for your explanation.
Its very easy to understand
Excellant explantion
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?
That was so easy explanation to a tough topic. Keep writing and help others to gain knowledge.
Thanks again.
Yes. It does. Infact String Intern is an implementation of Fly-Weight DP.
Your explanation was very helpful. I was having trouble understanding it from Eckel’s book and then from Wikipedia. Thanks :).
thank you, it is very helpfull.
Thanks a lot, its very much helpful.