joydip_kanjilal
Contributor

How to use the flyweight design pattern in C#

how-to
Jan 08, 20205 mins
C#Microsoft .NETSoftware Development

Take advantage of the flyweight design pattern to reduce memory consumption when working with many similar objects.

green concentric binary circles background pattern
Credit: thinkstock

Design patterns help us solve design problems often encountered in software development and reduce the complexities in our code. The Gang of Four design patterns fall into three categories: creational, structural, and behavioral.

The flyweight design pattern falls in the structural category. The flyweight pattern helps reduce memory consumption when working with many similar objects at the same time. This article examines how we can work with the flyweight design pattern in C#.

To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here.

Create a console application project in Visual Studio

First off, let’s create a .NET Core Console Application project in Visual Studio. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new .NET Core Console Application project in Visual Studio.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Click Create.

You should now have a new .NET Core console application project ready to go in Visual Studio 2019. We’ll use this project in the subsequent sections of this article.

The flyweight design pattern and its usage

The flyweight design pattern reduces the amount of memory required to create a number of large objects of the identical type in an application. The flyweight is an object that reduces memory pressure by sharing data with similar objects. Thus a new object is created only if needed, i.e., if no matching object is available. By reducing the memory intake, the flyweight pattern improves performance.

A typical use case for the flyweight pattern is when you need to create large objects of the same type. The Gang of Four description: “Use sharing to support large numbers of fine-grained objects efficiently.”

A flyweight object can have either of the following states:

  • Intrinsic state — the data is state-independent and is typically stored inside the flyweight object and can be shared
  • Extrinsic state — the data is state-dependent and hence it cannot be shared

The participants in the flyweight design pattern include the following:

  • Flyweight — this is typically an interface for the flyweight objects
  • ConcreteFlyweight — this is a class that implements the Flyweight interface
  • FlyweightFactory — this is a factory class used to create concrete objects of the ConcreteFlyweight type
  • Client — this stores references to the flyweight instances

Implement Flyweight abstract class and method in C#

To implement the flyweight design pattern in C#, let’s start by defining the abstract base class named Flyweight. This class will contain the declaration of an abstract method named Display. The following code snippet illustrates the Flyweight abstract class.

public abstract class Flyweight
 {
     public abstract void Display();
 }

The ConcreteFlyweight class extends the Flyweight class and implements the abstract method. The following code listing shows the ConcreteFlyweight class.

public class ConcreteFlyweight : Flyweight
    {
        private readonly string _key = null;
        public ConcreteFlyweight(string key)
        {
            _key = key;
        }
        public override void Display()
        {
            Console.WriteLine("The Key is: "+ _key);
        }
    }

Implement the FlyweightFactory class in C#

The FlyweightFactory class creates and stores flyweight instances in an instance of Dictionary. This class contains the GetFlyweight() method that returns a ConcreteFlyweight instance based on a given key. If the instance is present in the Dictionary then it is returned, else a new instance of ConcreteFlyweight is created and returned. The following code listing illustrates the FlyweightFactory class.

public class FlyweightFactory
    {
        private Dictionary<string, Flyweight> flyweights = new
        Dictionary<string, Flyweight>();
        public Flyweight GetFlyweight(string key)
        {
            Flyweight flyweight = null;
            if (flyweights.ContainsKey(key))
            {
                flyweight = flyweights[key];
            }
            else
            {
                flyweight = new ConcreteFlyweight(key);
                flyweights.Add(key, flyweight);
            }
            return flyweight;
        }
    }

Note that in this example we are using one ConcreteFlyweight class. Multiple instances of this class differ from one another on the value of the key. In practice, you might want to create several concrete classes that extend the Flyweight class. We’ve omitted multiple instances here for simplicity.

Implement the Flyweight client in C#

Lastly, here is what the client would look like.

static void Main(string[] args)
{
  var factory = new FlyweightFactory();
  var flyweight = factory.GetFlyweight("A");
  flyweight.Display();
  Console.Read();
}

Flyweight design pattern example in C#

Here is the complete program for your reference.

public abstract class Flyweight
    {
        public abstract void Display();
    }
    public class ConcreteFlyweight : Flyweight
    {
        private readonly string _key = null;
        public ConcreteFlyweight(string key)
        {
            _key = key;
        }
        public override void Display()
        {
            Console.WriteLine("The Key is: "+ _key);
        }
    }
    public class FlyweightFactory
    {
        private Dictionary<string, Flyweight> flyweights = new
        Dictionary<string, Flyweight>();
        public Flyweight GetFlyweight(string key)
        {
            Flyweight flyweight = null;
            if (flyweights.ContainsKey(key))
            {
                flyweight = flyweights[key];
            }
            else
            {
                flyweight = new ConcreteFlyweight(key);
                flyweights.Add(key, flyweight);
            }
            return flyweight;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var factory = new FlyweightFactory();
            var flyweight = factory.GetFlyweight("A");
            flyweight.Display();
            Console.Read();
        }
    }

When you execute the above program, you should see the following output. 

flyweight design pattern c IDG

Figure 1: The flyweight design pattern in action!

You can take advantage of the flyweight design pattern in scenarios where availability of memory is a constraint. However, in practice, the complexities involved in implementing the flyweight design pattern often outweigh the benefits. Hence, the usefulness of the flyweight pattern is limited. In many cases, a better alternative is the Prototype design pattern.

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author