Flyweight Design Pattern

1 year ago codedestine 0

According to GoF (Gang of Four), flyweight design pattern intent is:
“Use sharing to support large numbers of fine-grained objects efficiently”

Flyweight design pattern is used when a program need to create huge (usually in thousands or in millions) number of objects of a Class that share (similar) some state among them. By using this design pattern, we can reduce number of objects created by the program, which will decrease memory footprint and increase overall performance of the Application. Flyweight design pattern is an example of Structural design pattern as it reduce number of objects counts thus changing the structure of the Application.

Flyweight Design Pattern

How to apply

To apply flyweight design pattern, first we will divide state (class members) of our Class into two different types based on following criteria :-

  1. State (class members) of the Class, which can have few number of different values. We will use these states to create object of the Class by passing to its constructor.
  2. State (class members) of the Class, which can have huge number of different values. We will set these states through its setter after creating the object of the Class.

Example 

I have an application which draws scatter chart on mobile devices. In scatter chart, we can have multiple series represented by different colors (say blue, green or orange) and each series can have multiple points represented by circle filled with a color of its series.

Scatter Chart

First we create an Interface Pointer, which define behaviors for our class.


package com.blog.codedestine;

import java.awt.Graphics;

public interface Pointer {

   public void draw(Graphics g);

}

Second we create a Class ScatterPointer, which implements Pointer interface. ScatterPointer class has four class members :-

  1. Color :- This define color of scatter point, which can be of two type blue or orange. So we use this State for creating ScatterPointer object.
  2. Radius :- This define radius of scatter point, which can have one value (as per our application). So we use this State for creating ScatterPointer object.
  3.  X :- This define X coordinate of scatter point, which can have large number of different values. So we set this State through setter method.
  4. Y :- This define Y coordinate of scatter point, which can have large number of different values. So we set this State through setter method.
package com.blog.codedestine;

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

public class ScatterPointer implements Pointer {
    
    private Color color;
    private int radius;
    
    public ScatterPointer(Color color,int radius) {
        super();
        this.color = color;
        this.radius = radius;
        System.out.println(color.toString());
    }

    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public void draw(Graphics g) {
        g.setColor(color);
        g.fillOval(getX(),getY(),radius,radius);
    }
}

Third we create flyweight factory class FlyweightFactory, which is used by our program to instantiate Object of ScatterPointer. This factory store objects of  ScatterPointer in a HashMap. When our program makes a call to get an instance of ScatterPointer Object, it should be returned from the HashMap, if not found, then factory create a new Object of ScatterPointer and put in the Map and then return it.

package com.blog.codedestine;

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

public class FlyweightFactory {

    private static final Map<PointerColorType,ScatterPointer> pointers = new HashMap<PointerColorType,ScatterPointer>();

    public static ScatterPointer getScatterPointer(PointerColorType type) {
        ScatterPointer pointer = pointers.get(type);

        if (pointer == null) {
            if (type.equals(PointerColorType.COLOR_BLUE)) {
                pointer = new ScatterPointer(Color.BLUE,10);
            } else if (type.equals(PointerColorType.COLOR_ORANGE)) {
                pointer = new ScatterPointer(Color.ORANGE,10);
            } else if (type.equals(PointerColorType.COLOR_RED)) {
                pointer = new ScatterPointer(Color.RED,10);
            }
            pointers.put(type,pointer);
        }
        return pointer;
    }
    
    public static enum PointerColorType{
        COLOR_BLUE,COLOR_ORANGE,COLOR_RED;
    }    
}

Fourth we create demo class FlyweightDesignPatternDemo. Use the factory to get object of concrete class by passing an information such as color.

package com.blog.codedestine;

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;

import com.blog.codedestine.FlyweightFactory.PointerColorType;

public class FlyweightDesignPatternClient extends JFrame{
    
    private static final long serialVersionUID = 1L;
    private final int WIDTH;
    private final int HEIGHT;

    private static final PointerColorType colors[] = {PointerColorType.COLOR_RED,PointerColorType.COLOR_ORANGE,PointerColorType.COLOR_BLUE };
    
    public FlyweightDesignPatternClient(int width, int height){
        this.WIDTH=width;
        this.HEIGHT=height;
        Container contentPane = getContentPane();

        JButton startButton = new JButton("Scatter");
        final JPanel panel = new JPanel();

        contentPane.add(panel, BorderLayout.CENTER);
        contentPane.add(startButton, BorderLayout.SOUTH);
        setSize(WIDTH, HEIGHT);
        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 < 200; ++i) {
                    ScatterPointer pointer = FlyweightFactory.getScatterPointer(getRandomColor());
                    pointer.setX(getRandomX());
                    pointer.setY(getRandomY());
                    pointer.draw(g);
                }
            }
        });
    }    
    
    private int getRandomX() {
        return (int) (Math.random() * WIDTH);
    }

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

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

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

Result

After analyzing the result, we can notice that 200 scatter points has been drawn on JPanel but only four objects of ScatterPointer has been created.

scatter

scatterresult

Example in JDK

Java String Class’s String Pool implementation and wrapper class’s valueOf() method is an example of flyweight design pattern in JDK.

Advantage of Flyweight Pattern

  1. It reduce the number of objects of particular type (Class).
  2. It reduce memory footprint of the application and hence increase its performance.

Usage of Flyweight Pattern

  1. when an application need to create huge (usually in thousands or in millions) number of objects of a Class.
  2. When an application run on low memory devices such as mobile handset or any embedded system.
  3. When the application is throwing memory out of exception, because of huge number of objects of particular type (Class) is created by the application.

That’s all for flyweight design pattern, If you liked it, please share your thoughts in comments section and share it with others too. For more design patterns visit Design Patterns.