Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Flyweight Design Pattern- C#

4.79/5 (8 votes)
7 Jul 2014CPOL6 min read 36.3K  
Implementing flyweight design pattern using C#

Introduction

This article explains what is a flyweight design pattern and how we can implement it in C#.

Background

The flyweight design pattern although not widely used can be very helpful in scenarios where memory is a constraint. In a simple sentence flyweight pattern can be applied in situations where we want to limit the number of objects creation. Did I say “Limit the number of objects creation”? But we are living in an object oriented world how can we minimize the objects creation? So I will revisit the definition of flyweight. According to the GOF definition- “A flyweight is a shared object that can be used in multiple contexts simultaneously”. So think of why this pattern is called a flyweight? The word “flyweight-in software” is similar to the word “flyweight- in boxing” in which flyweight refers to a lightweight boxing category. In the same way we have a lightweight object (not the boxer) which can be used at various places in the system simultaneously.

A flyweight object can be described by 2 states:-

  1. Intrinsic State- Intrinsic state as the name suggests is the one which is natural to the flyweight object and can be shared. The intrinsic state is independent of flyweight’s context.
  2. Extrinsic state- The extrinsic state is one which varies with flyweight context and therefore it cannot be shared.

To make distinction between intrinsic and extrinsic state, let’s look at a very famous example (also mentioned in GOF book). A word processor has to play with character objects. If we look at a character object in a word processor its state would be its font, its style, its location, its actual content. Looking at just this example we can see that everything like the font, style, location of a character can vary for a character but the content of a character can be same ( at least it would be one among the 26 characters [a-z] forget about the constants for now). So character’s font, its style, its position all are extrinsic state as they varies and cannot be shared. Character’s content (like “a”,”b” ...) can be shared and comprises the intrinsic state. So we can derive that if we have a system where we need to create lot of objects and where each of these object can be described by a common intrinsic state and extrinsic state, we smell of applying flyweight pattern in such a system.

Let’s look at the UML diagram and various participants of a flyweight pattern.

 

Image 1

 

FlyweightFactory: As the name says all, since it’s a factory it manages flyweights. When a flyweight object is requested the factory returns the instance if it is present otherwise it creates a new flyweight, adds into the factory cache and returns.

IFlyweight: This is the interface which the flyweight implements. The GetExtrinsicState method gets the extrinsic state and IntrinsicState holds the intrinsic state of the flyweight.

ConcreteFlyweight: This is the actual flyweight object and is shareable. It stores the intrinsicState and derives the extrinsic state.

Using the code

Now consider an example where we would implement the flyweight pattern. Suppose we have to create an animated game where my favorite cartoon character has to collect money falling from the sky.

Do you smell flyweight pattern anywhere here? Now since we need to track of how much amount of money is collected by “Cartoon Character” we will create “objects” of these individual currency denominations, so that we can calculate the total. Since in this animated game we would have lot of money falling from the sky, imagine how much memory an object of “paper currency” would take? An object of currency in typical would have a graphical pictures of the national heroes, artistic fonts and lot of other stuff which would always be same for these objects. Similarly every denomination of metallic currency would be a somewhat similar object. So instead of creating thousands of objects for these falling money we would create just 2 objects one for the metallic currency and one for the paper currency. Furthermore since various properties of these objects can be easily classified into intrinsic state and extrinsic state, so this would be an ideal scenario where we can apply the flyweight pattern. The table below shows the intrinsic and extrinsic state of the paper currency.

Paper Currency

Image 2

Based on the above scenario/problem let’s look at the code and see the use of flyweight pattern. (Note: In the above we can create flyweights of individual denomination currency but for the simplicity of code I had refrained myself doing that, there by just creating flyweights of metallic currency and paper currency).

C#
public enum EnMoneyType
{
  Metallic,
  Paper
}

public interface IMoney
{
  EnMoneyType MoneyType { get; } //IntrinsicState()
  void GetDisplayOfMoneyFalling(int moneyValue); //GetExtrinsicSate()
}

The above interface “IMoney” corresponds to the IFlyweight interface. The MoneyType would hold the IntrinsicState (Metallic money, paper money would be the intrinsic states of the flyweight classes) and the operation GetDisplayOfMoneyFalling would act on the extrinsic state of the flyweight which is the currency denomination.

C#
public class MetallicMoney:IMoney
{
   public EnMoneyType MoneyType
   {
     get { return EnMoneyType.Metallic; }
   }

   public void GetDisplayOfMoneyFalling(int moneyValue)
   {
     //This method would display graphical representation of a metallic currency like a    
       gold coin.
       Console.WriteLine(string.Format("Displaying a graphical object of {0} currency of 
                                        value ${1} falling from sky."
                                        , MoneyType.ToString(), moneyValue)
                                      );
   }
}

This is the concrete flyweight “metallic money” class which would implement the IMoney interface. This is the flyweight which would be used to create different objects (each having different extrinsic state.) The extrinsic state here would be the moneyValue and the intrinsic state would be the Metallic money.

C#
class PaperMoney:IMoney
{
  public EnMoneyType MoneyType
  {
    get { return EnMoneyType.Paper; }
  }

  public void GetDisplayOfMoneyFalling(int moneyValue) //GetExtrinsicState()
  {
    // This method would display a graphical representation of a paper currency.
       Console.WriteLine(string.Format("Displaying a graphical object of {0} currency                                        of value ${1} falling from sky."
                                       ,MoneyType.ToString(), moneyValue));
  }
}

This is another concrete flyweight which will be used to create multiple objects.It’s intrinsic state is the “Paper Money” and extrinsic state would be the moneyValue(currency Denomination).

C#
public class MoneyFactory
{
   public static int ObjectsCount=0;
   private Dictionary<enmoneytype,imoney> _moneyObjects;
   public IMoney GetMoneyToDisplay(EnMoneyType form) // Same as GetFlyWeight()
   {
      if (_moneyObjects == null)
           _moneyObjects = new Dictionary<enmoneytype,>();
      if (_moneyObjects.ContainsKey(form))
            return _moneyObjects[form];
      switch (form)
      {
          case EnMoneyType.Metallic:
              _moneyObjects.Add(form, new MetallicMoney());
               ObjectsCount++;
               break;
          case EnMoneyType.Paper:
              _moneyObjects.Add(form, new PaperMoney());
               ObjectsCount++;
               break;
          default:
               break;
      }
      return _moneyObjects[form];
   }
}

So this “MoneyFactory” class is our flyweight factory which manages the creations of flyweights and ensures that if the object is already there in the dictionary it returns the instance of that otherwise it creates the new object. The above class also keeps the track of number of objects created through the ObjectsCount variable.

Now let’s look at our client which would make use of the flyweight pattern.

C#
class Program
{
   static void Main(string[] args)
   {
     const int ONE_MILLION=10000; // <--- Suppose this is one million :)
     int[] currencyDenominations = new[] { 1, 5, 10, 20, 50, 100 };
     MoneyFactory moneyFactory = new MoneyFactory();
     int sum = 0;
     while (sum <= ONE_MILLION)
     {
       IMoney graphicalMoneyObj=null;
       Random rand = new Random();
       int currencyDisplayValue=currencyDenominations[rand.Next(0,currencyDenominations
                                                      .Length)];
       if (currencyDisplayValue == 1 || currencyDisplayValue==5)
          graphicalMoneyObj=moneyFactory.GetMoneyToDisplay(EnMoneyType.Metallic);
       else
          graphicalMoneyObj=moneyFactory.GetMoneyToDisplay(EnMoneyType.Paper);
                
       graphicalMoneyObj.GetDisplayOfMoneyFalling(currencyDisplayValue);
       sum = sum + currencyDisplayValue;
     }
     Console.WriteLine("Total Objects created="+ MoneyFactory.ObjectsCount.ToString());
            Console.ReadLine();
        }
}

The client gets an instance of flyweight and shows the result (graphical result of money falling from the sky-forget the actual implementation for now). Over here we are looping till the count of money dropping from sky is one million. We generate few random currency denominations to drop random denominations of money from the sky. If the currency denomination is 1 or 5 we are dropping metallic money otherwise we are dropping paper money and that completes our game….

The output of the program would be something like this.

Image 3

And the total number of objects created would be

Image 4

Points of Interest

So from the above code we can figure out that flyweight pattern would be very useful in scenarios where similar kinds of objects are to be created with a slight variance. Flyweight pattern would save us the memory space and would let us write the code which deals with lesser number of objects.

History

Version 1.0 (6/07/2014)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)