RO EN

Flyweight Pattern – memory optimization through object reuse

Flyweight Pattern – memory optimization through object reuse
Doru Bulubasa
05 December 2025

When you develop applications that process a very large number of objects โ€“ long lists, graph nodes, characters, repetitive structures โ€“ memory consumption can quickly become a problem.

This is where the Flyweight Pattern comes in, a Structural Design Pattern that allows sharing of common objects, massively reducing allocated memory.


๐Ÿ” What is the Flyweight Pattern?

Flyweight is a pattern that separates intrinsic state (which can be shared) from extrinsic state (specific to each object).

Thus, instead of creating thousands or millions of identical objects, you reuse already created instances.

It is especially useful in applications with:

  • many repeated graphic elements

  • large data lists

  • character-by-character texts

  • cache scenarios

  • document or map generation


๐Ÿง  Concept in brief

Objects are divided into:

  • Intrinsic state โ€“ properties common to all instances

  • Extrinsic state โ€“ values specific to each usage

The key thing: only the extrinsic state is passed at runtime, and intrinsic objects are reused.


๐Ÿ— Structure of actors

  • Flyweight โ€“ the interface used by all shared objects

  • ConcreteFlyweight โ€“ reusable object containing intrinsic state

  • FlyweightFactory โ€“ creates and manages common instances

  • Client โ€“ provides extrinsic state and uses the flyweight


๐Ÿงช Practical example in C#

Scenario: we manage the characters of a text in an editor. The letters are identical in shape, differing only in their positions on the screen.

๐ŸŽฏ 1. Flyweight Interface

public interface ICharacterFlyweight
{
    void Render(int fontSize, int x, int y);
}


๐ŸŽฏ 2. Concrete Flyweight (intrinsic state)

public class CharacterFlyweight : ICharacterFlyweight
{
    private readonly char _symbol; // intrinsic

    public CharacterFlyweight(char symbol)
    {
        _symbol = symbol;
    }

    public void Render(int fontSize, int x, int y)
    {
        Console.WriteLine($"Rendering '{_symbol}' at ({x},{y}) with size {fontSize}");
    }
}


๐ŸŽฏ 3. Flyweight Factory (character cache)

public class CharacterFlyweightFactory
{
    private readonly Dictionary<char, ICharacterFlyweight> _characters = new();

    public ICharacterFlyweight GetFlyweight(char symbol)
    {
        if (!_characters.ContainsKey(symbol))
        {
            _characters[symbol] = new CharacterFlyweight(symbol);
            Console.WriteLine($"Creating new flyweight for '{symbol}'");
        }

        return _characters[symbol];
    }
}


๐ŸŽฏ 4. Using Flyweight in an application

var factory = new CharacterFlyweightFactory();
string text = "AAABBC";

int x = 0;
foreach (char c in text)
{
    var character = factory.GetFlyweight(c);
    character.Render(fontSize: 12, x: x, y: 10);
    x += 10;
}


๐Ÿ“‰ Benefits

โœ” Reduced memory consumption

โœ” High scalability in repetitive structures

โœ” Performance improvement in graphic, map, cache scenarios

โš  Disadvantages

โŒ Requires careful separation of intrinsic/extrinsic state

โŒ Increases code complexity

โŒ Can be over-engineering if the number of objects is not large


๐Ÿงญ When to use Flyweight?

Use it when:

  • you have very many similar objects

  • memory consumption becomes a problem

  • objects share a large part of behavior/state

  • you want a cache of reusable objects

Avoid it if:

  • objects are few

  • extrinsic state is complicated

  • differences between instances are large


๐Ÿ”š Conclusion

The Flyweight Pattern is essential for memory optimization in large, repetitive, or graphic applications. By separating states and reusing common objects, you can dramatically reduce the RAM footprint while maintaining the same functional behavior.

If your .NET application processes millions of elements, this pattern can make the difference between a slow and a performant system.