Here, we will see how to create Flyweight Design Pattern with example.
The Flyweight design pattern is a structural pattern used to minimize memory usage by sharing as much data as possible with similar objects. It is particularly useful when a large number of objects are created, but many share common internal data. The key idea is to split object data into intrinsic (shared) and extrinsic (unique) states, with shared states being reused to reduce memory consumption.
In a chess game, you have two types of pieces, black and white. However, you don't need to create separate objects for each piece on the board. You can reuse the objects for similar pieces (e.g., black pawns) by only differentiating their positions on the board. The shared intrinsic state (type, color, movement rules) can be reused, while extrinsic state (position) can be passed in dynamically. We will explain in detail lator part of the article with code example.
Examples
In a chess game, you have two types of pieces, black and white. However, you don't need to create separate objects for each piece on the board. You can reuse the objects for similar pieces (e.g., black pawns) by only differentiating their positions on the board. The shared intrinsic state (type, color, movement rules) can be reused, while extrinsic state (position) can be passed in dynamically.
Using the Flyweight pattern allows us to optimize memory usage by sharing the intrinsic (common) state of the pieces and handling the extrinsic (unique) state separately.
These properties are shared among all instances of the same type and color. For example, all black pawns share the same type, color, and movement rules.
This property is unique for each piece and is not shared.
Below is a comprehensive C# example demonstrating the Flyweight pattern applied to a chess game.
using System;
using System.Collections.Generic;
// Flyweight Interface
public interface IChessPiece
{
void Display(Position position);
}
// Concrete Flyweight
public class ChessPiece : IChessPiece
{
private readonly string _type; // Intrinsic State
private readonly string _color; // Intrinsic State
public ChessPiece(string type, string color)
{
_type = type;
_color = color;
}
public void Display(Position position)
{
Console.WriteLine($"{_color} {_type} at {position}");
}
}
// Flyweight Factory
public class ChessPieceFactory
{
private readonly Dictionary _pieces = new Dictionary();
public IChessPiece GetChessPiece(string type, string color)
{
string key = $"{color}_{type}";
if (_pieces.ContainsKey(key))
{
return _pieces[key];
}
else
{
IChessPiece piece = new ChessPiece(type, color);
_pieces.Add(key, piece);
Console.WriteLine($"Created new {color} {type}.");
return piece;
}
}
public int GetTotalPieces()
{
return _pieces.Count;
}
}
// Position Class (Extrinsic State)
public class Position
{
public string Row { get; }
public string Column { get; }
public Position(string column, string row)
{
Column = column;
Row = row;
}
public override string ToString()
{
return $"{Column}{Row}";
}
}
// Client
public class ChessBoard
{
private readonly ChessPieceFactory _factory;
private readonly List<(IChessPiece, Position)> _board = new List<(IChessPiece, Position)>();
public ChessBoard(ChessPieceFactory factory)
{
_factory = factory;
}
public void AddPiece(string type, string color, string column, string row)
{
IChessPiece piece = _factory.GetChessPiece(type, color);
Position position = new Position(column, row);
_board.Add((piece, position));
}
public void DisplayBoard()
{
foreach (var (piece, position) in _board)
{
piece.Display(position);
}
}
}
// Example Usage
public class Program
{
public static void Main()
{
ChessPieceFactory factory = new ChessPieceFactory();
ChessBoard board = new ChessBoard(factory);
// Adding Black Pawns
for (int i = 1; i <= 8; i++)
{
board.AddPiece("Pawn", "Black", ((char)('A' + i - 1)).ToString(), "7");
}
// Adding White Pawns
for (int i = 1; i <= 8; i++)
{
board.AddPiece("Pawn", "White", ((char)('A' + i - 1)).ToString(), "2");
}
// Adding Black Rook
board.AddPiece("Rook", "Black", "A", "8");
board.AddPiece("Rook", "Black", "H", "8");
// Adding White Rook
board.AddPiece("Rook", "White", "A", "1");
board.AddPiece("Rook", "White", "H", "1");
// Display all pieces
board.DisplayBoard();
Console.WriteLine($"\nTotal unique chess piece objects created: {factory.GetTotalPieces()}");
}
}
Explanation
Output