Take advantage of the flyweight design pattern to reduce memory consumption when working with many similar objects. 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. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. 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. 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. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos