Advanced Java September 20 ,2025

Flyweight Design Pattern in Java

Introduction

In large-scale software systems, creating a huge number of objects can consume significant memory, especially if many objects share common intrinsic data. The Flyweight Pattern addresses this issue by sharing objects that are similar to minimize memory usage while maintaining unique external states.

Think of it like a forest of trees in a game: instead of creating a separate object for each tree, trees of the same type share common characteristics (like texture and color) while only storing unique positions.

Definition

The Flyweight Pattern is a structural design pattern that reduces memory usage by sharing as much data as possible with similar objects.

Key Idea: Separate intrinsic state (shared) from extrinsic state (unique per object) and reuse objects whenever possible.

  • Intrinsic State: Shared, stored inside the flyweight object.
  • Extrinsic State: Unique to each object, passed from the client.

Intrinsic vs. Extrinsic State

1. Intrinsic State

  • Definition:
    The part of the object’s state that is invariant (does not change) and can be shared across multiple objects.
  • Stored Inside Flyweight Object
    Since intrinsic data is common, it is kept inside the flyweight object itself.
  • Example in Real Life:
    • In a text editor, the font style or character shape (like "Arial", "Times New Roman") is intrinsic. The same "A" shape can be reused everywhere.
    • In a game with millions of trees, the tree type (e.g., "Oak", "Pine") is intrinsic because many trees share the same type.

2. Extrinsic State

  • Definition:
    The part of the object’s state that is variant (changes per object) and cannot be shared.
  • Passed from the Client
    Since it depends on the context, extrinsic data is not stored inside the flyweight object. Instead, it is provided externally whenever needed.
  • Example in Real Life:
    • In the text editor, the position of a character (row, column) is extrinsic because each "A" may appear at a different location.
    • In the game example, the tree’s coordinates (x, y, z position) are extrinsic because every tree stands in a different place.

Why Separate These States?

The benefit of separating intrinsic and extrinsic state is memory optimization.

  • If both intrinsic and extrinsic state were stored in each object, you would end up creating thousands of heavy objects.
  • By storing only intrinsic (shared) data in a flyweight object and passing extrinsic (unique) data when needed, you can drastically cut down on memory usage.

Example in Java: Characters in a Document

// Flyweight
interface Character {
    void display(int row, int column); // extrinsic state (position)
}

// Concrete Flyweight
class ConcreteCharacter implements Character {
    private final char symbol; // intrinsic state

    public ConcreteCharacter(char symbol) {
        this.symbol = symbol;
    }

    @Override
    public void display(int row, int column) {
        System.out.println("Character: " + symbol + 
                           " | Position: (" + row + ", " + column + ")");
    }
}

// Flyweight Factory
class CharacterFactory {
    private final java.util.Map pool = new java.util.HashMap<>();

    public Character getCharacter(char symbol) {
        pool.putIfAbsent(symbol, new ConcreteCharacter(symbol));
        return pool.get(symbol);
    }
}

// Client
public class FlyweightDemo {
    public static void main(String[] args) {
        CharacterFactory factory = new CharacterFactory();

        Character a1 = factory.getCharacter('A'); // reused
        Character a2 = factory.getCharacter('A'); // same object reused
        Character b = factory.getCharacter('B');

        a1.display(0, 1); // extrinsic state
        a2.display(0, 2); // extrinsic state
        b.display(0, 3);  // extrinsic state

        System.out.println("a1 and a2 are same object? " + (a1 == a2));
    }
}

Output

Character: A | Position: (0, 1)
Character: A | Position: (0, 2)
Character: B | Position: (0, 3)
a1 and a2 are same object? true

Explanation of States in Example

  • Intrinsic State (shared):
    The actual character symbol 'A' or 'B'. This is stored inside the ConcreteCharacter flyweight object.
  • Extrinsic State (unique):
    The position (row, column) of each character. This is passed by the client at runtime when calling display().

Real-World Applications

  1. Text Editors: Characters stored as flyweights; positions are extrinsic.
  2. Game Development: Trees, cars, bullets – type/model is intrinsic, location is extrinsic.
  3. GUI Systems: Icons/images are intrinsic, positions and states are extrinsic.
  4. Document Rendering (PDF/Word): Same font glyphs reused at different positions.

When to Use the Flyweight Pattern

  • When many objects are needed that share common data.
  • When memory usage is critical.
  • When objects can be decomposed into intrinsic and extrinsic states.
  • In gaming, graphics, or document editing applications where similar objects repeat frequently.

Real-World Example

  • Text Editor: Each character on the screen shares the same font, size, and style (intrinsic state), but their position in the document is unique (extrinsic state).
  • Chess Game: All white pawns share the same representation (intrinsic state) while their board positions differ (extrinsic state).

Java Implementation

Let’s implement a Flyweight Pattern example for drawing colored circles.

Step 1: Define the Flyweight Interface

// Flyweight interface
interface Shape {
    void draw(int x, int y); // Extrinsic state passed here
}

Step 2: Create Concrete Flyweight

// Concrete Flyweight
class Circle implements Shape {
    private String color;  // Intrinsic state

    public Circle(String color) {
        this.color = color;
        System.out.println("Creating a circle of color: " + color);
    }

    @Override
    public void draw(int x, int y) {
        System.out.println("Drawing " + color + " circle at (" + x + ", " + y + ")");
    }
}

Step 3: Implement Flyweight Factory

import java.util.HashMap;
import java.util.Map;

// Flyweight Factory
class ShapeFactory {
    private static final Map circleMap = new HashMap<>();

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

        if (circle == null) {
            circle = new Circle(color); // Create only if not exists
            circleMap.put(color, circle);
        }
        return circle;
    }
}

Step 4: Client Usage

public class Main {
    public static void main(String[] args) {
        Shape redCircle1 = ShapeFactory.getCircle("Red");
        redCircle1.draw(10, 20);

        Shape redCircle2 = ShapeFactory.getCircle("Red");
        redCircle2.draw(30, 40);

        Shape blueCircle = ShapeFactory.getCircle("Blue");
        blueCircle.draw(50, 60);
    }
}

Output:

Creating a circle of color: Red
Drawing Red circle at (10, 20)
Drawing Red circle at (30, 40)
Creating a circle of color: Blue
Drawing Blue circle at (50, 60)

Observation: The red circle object is reused, avoiding additional memory allocation.

Advantages of the Flyweight Pattern

  1. Memory Optimization: Reduces memory usage by reusing objects.
  2. High Performance: Less memory allocation leads to faster object creation.
  3. Scalable Systems: Suitable for systems with a huge number of similar objects.
  4. Separates Intrinsic and Extrinsic States: Makes object design cleaner and more maintainable.

Disadvantages

  1. Complex Implementation: Requires careful separation of intrinsic and extrinsic states.
  2. Clients Must Manage Extrinsic State: Mismanagement can lead to errors.
  3. Overhead of Object Management: Maintaining flyweight pools may increase code complexity.

Summary

The Flyweight Pattern is a powerful memory optimization technique for applications that require a large number of similar objects. By sharing intrinsic state and externalizing unique state, it provides scalability, efficiency, and flexibility.

Next, we will explore the Proxy Pattern, which controls access to objects by providing substitutes or placeholders, enabling lazy loading, access control, and security.

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com