Easy Tutorial
❮ Memento Pattern Data Access Object Pattern ❯

Flyweight Pattern

The Flyweight Pattern is primarily used to reduce the number of objects created, thereby reducing memory usage and improving performance. This type of design pattern falls under the structural pattern category, providing a way to decrease object count, thus enhancing the object structure of applications.

The Flyweight Pattern attempts to reuse existing similar objects, creating new ones only when no matching object is found. We will demonstrate this pattern by creating 5 objects to draw 20 circles at different positions. Since there are only 5 available colors, the color attribute is used to check for existing Circle objects.

Introduction

Intent: To support a large number of fine-grained objects efficiently by sharing them.

Main Problem: With a large number of objects, memory overflow might occur. We abstract the common parts and return existing objects in memory for identical requests, avoiding re-creation.

When to Use:

  1. The system has a large number of objects.
  2. These objects consume a lot of memory.
  3. Most object states can be externalized.
  4. Objects can be grouped by intrinsic states. When extrinsic states are removed, each group can be represented by one object.
  5. The system does not depend on object identity, which is indistinguishable.

How to Solve: Use a unique identifier to check if an object exists in memory, returning it if found.

Key Code: Store objects in a HashMap.

Examples:

  1. Java's String, returning existing strings or creating new ones in the string pool.
  2. Database connection pools.

Advantages: Significantly reduces object creation, lowers system memory usage, and improves efficiency.

Disadvantages: Increases system complexity by requiring separation of intrinsic and extrinsic states. Extrinsic states should not change with intrinsic states to avoid system confusion.

Scenarios:

  1. Systems with many similar objects.
  2. Scenarios requiring buffer pools.

Considerations:

  1. Carefully separate intrinsic and extrinsic states to avoid thread safety issues.
  2. These classes must be controlled by a factory object.

Implementation

We will create a Shape interface and a concrete class Circle that implements the Shape interface. Next, we define a factory class ShapeFactory.

ShapeFactory has a HashMap of Circle objects keyed by the circle's color. It creates a circle of a specific color whenever a request is received. ShapeFactory checks its HashMap for a Circle object; if found, it returns that object; otherwise, it creates a new one stored in the hashmap for future use and returns it to the client.

The FlyWeightPatternDemo class uses ShapeFactory to get Shape objects. It passes color information (e.g., red/green/blue/black/white) to ShapeFactory to obtain the desired colored objects.

Step 1

Create an interface.

public interface Shape {
   void draw();
}

Step 2

Create a concrete class implementing the interface.

public class Circle implements Shape {
   private String color;
   private int x;
   private int y;
   private int radius;

   public Circle(String color){
      this.color = color;     
   }

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

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

   public void setRadius(int radius) {
      this.radius = radius;
   }

   @Override
   public void draw() {
      System.out.println("Circle: Draw() [Color : " + color 
         +", x : " + x +", y :" + y +", radius :" + radius);
   }
}

Step 3

Create a factory to generate objects based on given information.

import java.util.HashMap;

public class ShapeFactory {
   private static final HashMap&lt;String, Shape> circleMap = new HashMap<>();

   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

Step 4

Use the factory to get objects by passing color information.

public class FlyweightPatternDemo {
   private static final String colors[] = 
      { "Red", "Green", "Blue", "White", "Black" };
   public static void main(String[] args) {

      for(int i=0; i < 20; ++i) {
         Circle circle = 
            (Circle)ShapeFactory.getCircle(getRandomColor());
         circle.setX(getRandomX());
         circle.setY(getRandomY());
         circle.setRadius(100);
         circle.draw();
      }
   }
   private static String getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
   private static int getRandomX() {
      return (int)(Math.random()*100 );
   }
   private static int getRandomY() {
      return (int)(Math.random()*100);
   }
}

Step 5

Execute the program, outputting results:

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100
❮ Memento Pattern Data Access Object Pattern ❯