Flyweight Pattern

It is one of the structural design patterns.

It’s main intent as per GOF is “Use sharing to support large numbers of fine-grained objects efficiently”

This pattern should be used when we have high number of objects of almost same nature.

When we have high number of objects, memory consumption will be high

In this case, flyweight pattern helps in reducing the memory consumption by enabling the sharing of objects.

Sharing objects is the main key in this pattern.

In order to understand this pattern and its application properly, we need to have clear understanding of intrinsic and extrinsic properties of an object.

What are intrinsic and extrinsic properties ?


Intrinsic properties make the object unique and extrinsic properties are passed by the client code which will be used by the object to perform different operations

Extrinsic properties are also known as non-shareable properties of a class which are supplied from client.

Let’s see how Flyweight pattern works


This pattern mainly reduces the memory consumption when we have huge number of objects.

In order to do that, it creates cache of objects in a Hashmap and re-use those objects only instead of creating new objects all the time.

Example :
Assume we have a class called “Alphabet”.

How many objects will be required to represent each Alphabet ?


26 for lower case and 26 for upper case and total 52 objects are required.

Now assume we have to represent each alphabet with some font, color and size

Now we will end up with huge number of objects

Example :

Object 1 : Alphabet A with font italic , color blue and size 12
Object 2 : Alphabet A with font italic , color blue and size 14
Object 1 : Alphabet A with font italic , color blue and size 16
Object 1 : Alphabet A with font italic , color red and size 12
. . .
. . .
and so on.

Just for alphabet “A” will have so many objects, think of 52 alphabets.

In order to reduce the number of objects, we need to use flyweight pattern

We need to implement below 3 points to achieve flyweight pattern


1 ) First we need to identify intrinsic and extrinsic properties of a class

2 ) Create a cache of objects using Hashmap

3 ) Reuse the objects from cache

Implementation of flyweight pattern

Let’s consider the example of Forest where we will have many trees

Assume we need to grow similar trees in different parts of a forest.

Step 1

Create a class called Tree

  1. package com.kb.flyweight;
  2.  
  3. import java.awt.Graphics;
  4.  
  5. public class Tree {
  6.     private int x;
  7.     private int y;
  8.     private TreeType type;
  9.     public Tree(int x, int y, TreeType type) {
  10.         super();
  11.         this.x = x;
  12.         this.y = y;
  13.         this.type = type;
  14.     }
  15.    
  16.      public void draw(Graphics g) {
  17.             type.draw(g, x, y);
  18.         }
  19. }
package com.kb.flyweight;

import java.awt.Graphics;

public class Tree {
	private int x;
	private int y;
	private TreeType type;
	public Tree(int x, int y, TreeType type) {
		super();
		this.x = x;
		this.y = y;
		this.type = type;
	}
	
	 public void draw(Graphics g) {
	        type.draw(g, x, y);
	    }
}

Step 2

Create a class called TreeType

  1. package com.kb.flyweight;
  2.  
  3. import java.awt.Color;
  4. import java.awt.Graphics;
  5.  
  6. public class TreeType {
  7.     private String name;
  8.     private Color color;
  9.     public TreeType(String name, Color color) {
  10.         this.name = name;
  11.         this.color = color;
  12.     }
  13.    
  14.      public void draw(Graphics g, int x, int y) {
  15.    
  16.             g.setColor(color);
  17.             g.fillOval(x - 5, y - 10, 10, 10);
  18.         }
  19.  
  20. }
package com.kb.flyweight;

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

public class TreeType {
	private String name;
	private Color color;
	public TreeType(String name, Color color) {
		this.name = name;
		this.color = color;
	}
	
	 public void draw(Graphics g, int x, int y) {
	
	        g.setColor(color);
	        g.fillOval(x - 5, y - 10, 10, 10);
	    }

}

Step 3

Create a class TreeFactory which helps us to cache the similar trees

  1. package com.kb.flyweight;
  2.  
  3. import java.awt.Color;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6.  
  7. public class TreeFactory {
  8.    
  9.      static Map<String, TreeType> treeTypes = new HashMap<>();
  10.  
  11.      //Create new TreeType only if not available in Map
  12.         public static TreeType getTreeType(String name, Color color) {
  13.             TreeType result = treeTypes.get(name);
  14.             if (result == null) {
  15.                 result = new TreeType(name, color);
  16.                 treeTypes.put(name, result);
  17.             }
  18.             return result;
  19.         }
  20. }
package com.kb.flyweight;

import java.awt.Color;
import java.util.HashMap;
import java.util.Map;

public class TreeFactory {
	
	 static Map<String, TreeType> treeTypes = new HashMap<>();

	 //Create new TreeType only if not available in Map
	    public static TreeType getTreeType(String name, Color color) {
	        TreeType result = treeTypes.get(name);
	        if (result == null) {
	            result = new TreeType(name, color);
	            treeTypes.put(name, result);
	        }
	        return result;
	    }
}

Step 4

Create a forest class which extends AWT Jframe

It will have list of trees

  1. package com.kb.flyweight;
  2.  
  3. import java.awt.Color;
  4. import java.awt.Graphics;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7.  
  8. import javax.swing.JFrame;
  9.  
  10. public class Forest extends JFrame {
  11.     private List<Tree> trees = new ArrayList<>();
  12.  
  13.     public void plantTree(int x, int y, String name, Color color) {
  14.         TreeType type = TreeFactory.getTreeType(name, color);
  15.         Tree tree = new Tree(x, y, type);
  16.         trees.add(tree);
  17.     }
  18.  
  19.     @Override
  20.     public void paint(Graphics graphics) {
  21.         for (Tree tree : trees) {
  22.             tree.draw(graphics);
  23.         }
  24.     }
  25. }
package com.kb.flyweight;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

public class Forest extends JFrame {
    private List<Tree> trees = new ArrayList<>();

    public void plantTree(int x, int y, String name, Color color) {
        TreeType type = TreeFactory.getTreeType(name, color);
        Tree tree = new Tree(x, y, type);
        trees.add(tree);
    }

    @Override
    public void paint(Graphics graphics) {
        for (Tree tree : trees) {
            tree.draw(graphics);
        }
    }
}

Step 5

Create a client program

  1. package com.kb.flyweight;
  2.  
  3. import java.awt.Color;
  4.  
  5. public class FlyweightClient {
  6.  
  7.     public static void main(String[] args) {
  8.         Forest forest = new Forest();
  9. //Trying to create 1 lakh objects, but because of flyweight pattern,we will reuse and reduce the no of objects
  10.         for (int i = 0; i < 100000; i++) {
  11.             forest.plantTree(random(0, 200), random(0, 200), "Neem", Color.GREEN);
  12.             forest.plantTree(random(0, 200), random(0, 200), "Banyan", Color.YELLOW);
  13.         }
  14.  
  15.         forest.setSize(200, 200);
  16.         forest.setVisible(true);
  17.  
  18.         System.out.println(100000 + " trees drawn");
  19.  
  20.     }
  21.  
  22.     private static int random(int min, int max) {
  23.         return min + (int) (Math.random() * ((max - min) + 1));
  24.     }
  25.  
  26. }
package com.kb.flyweight;

import java.awt.Color;

public class FlyweightClient {

	public static void main(String[] args) {
		Forest forest = new Forest();
//Trying to create 1 lakh objects, but because of flyweight pattern,we will reuse and reduce the no of objects
		for (int i = 0; i < 100000; i++) {
			forest.plantTree(random(0, 200), random(0, 200), "Neem", Color.GREEN);
			forest.plantTree(random(0, 200), random(0, 200), "Banyan", Color.YELLOW);
		}

		forest.setSize(200, 200);
		forest.setVisible(true);

		System.out.println(100000 + " trees drawn");

	}

	private static int random(int min, int max) {
		return min + (int) (Math.random() * ((max - min) + 1));
	}

}



We can see the output image, In that 100000 objects are displayed but because of Flyweight pattern
We have reused many objects and reduced the memory consumption.

When to use Flyweight pattern ?


When we need to create large number of similar objects

When memory is a constraint as more objects consumes more memory

When most of the object attributes can be shared and made external


Where this pattern currently used ?

valueOf() method of all wrapper classes in java

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on

Comment (10)

  1. Hello

    I really liked your blog.however in this post i would like to add something ,

    you have mentioned there that

    *How we create object in Java ?

    Yes using constructor , and we should not allow users to access constructor and execute it every time they try to. *

    I believe this statement is completely wrong. constructor is executed that does not mean object is created. object is create only using new operator and constructor is executed to initialize the instance variable.

    Kindly correct it.. 🙂

    thanks again.

    1. Karibasappa G C (KB)
      Karibasappa G C (KB)

      Thanks PushP for bringing this into discussion!!

      Let me try to make you understand the below line
      we should not allow users to access constructor and execute it every time they try to.

      If we are making someone to access constructor I mean execute constructor multiple times it just creates new object according to Java concept.

      How ?
      you know that constructors don’t have names right,so the only we to make the constructor execution is by creating an object using new.
      I agree that constructor execution and object creation are different activities but my point here is when you allow someone to execute the constructor multiple times, it means you are calling constructors multiple times because there is no other way to execute the constructors.
      Note:going through programmatically not through reflection and all.

      your opinion
      constructor is executed that does not mean object is created , object is created only using new operator and constructor is executed to initialize the instance variable

      my understanding on your opinion
      if I go by English i agree with this sentence , but going by Java concept i can not agree with this.
      Because when constructor is executed it means that you have called it using new class_name(), it means one object gets created in Java.
      I am not saying constructor execution and object creation are synonyms but what i am saying is they are mutually dependent.

      So my point here is simple,
      we should not allow users create object multiple times which is same as we should not allow users to execute the constructors multiple times.

      preventing constructor execution is same as not allowing someone to create an object.

      Happy to hear your inputs again and Thank you so much !!

  2. karibasappagc

    Hi Mani,,,

    I have added subscribe option on the right sidebar, you can subscribe there to receive the updates 🙂

    Thank you once again…and welcome for your comments always.

  3. karibasappagc

    Hi Mani, Its really very good notice…

    I forgot to add clone and also i didn’t add one more approach using ENUM.

    But Reflection you are right , i didnt notice this situation. but its good to cover that as well.

    so i will edit this post sometime to include all the above scenarios.

    Thanks a lot for reading , observing the things and suggesting.

    Keep Suggesting the posts during your free time 🙂 Thank you once again…

  4. Manikandan Jayaraman

    Good one, KB 🙂

    I can break your code using reflection though:
    ===
    // Access constructor using reflection
    Class clazz = FinalSingleton.class;
    Constructor cons = clazz.getDeclaredConstructor();
    cons.setAccessible(true);
    FinalSingleton instanceThree = cons.newInstance();
    instanceThree.setX(300);
    System.out.println(“instanceThree.getX() :: “+instanceThree.getX());
    ===

    the above creates a new instance.you can avoid that by changig your constructor
    ===
    private FinalSingleton() {

    //If-block needed to avoid creation of another object using reflection
    /*if (LazyLoadFinalSingleton.SINGLETONINSTANCE != null) {
    throw new IllegalStateException(“Inside FinalSingleton(): instance already created.”);
    }*/

    x = 100;
    System.out.println(“Constructor Called. Instance created.”);
    }
    ===

    Also good to override clone method and throw clone not supported exception. You will never know where the loop hole is. 🙂

Leave a Comment

  • You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" extra="">

    • Please answer this simple challenge to post your valuable comment *