Categories: Design Pattern

Structural Patterns – Flyweight

Flyweight – A fine-grained instance is used for efficient sharing. Reduce the create object number and memory occupation, then improve the performance.

From Design Pattern – Structural Patterns

Structure

Flyweight pattern – Class diagram UML

Applicability

Using the flyweight pattern in the project only when the function must support a huge number of objects that barely fit into available RAM.

Pros and Cons

PROS

  • Save lots of RAM.

CONS

  • Maybe the trading RAM over CPU cycles when the context data needs to be recalculated each time somebody calls a flyweight method.
  • The code becomes much more complex, and then it will let new team members always wonder why it does and design.

How to Implement

#1 Basic Sample

class Program
{
 static void Main(string[] args)
 {
  var factory = new FlyweightFactory(
   new Profile { ID = 1, Name = "A", Age = 10, Address = "T"},
   new Profile { ID = 2, Name = "B", Age = 11, Address = "D" },
   new Profile { ID = 3, Name = "C", Age = 12, Address = "E" }
  );

  factory.ListFlyweights();

  AddToProfile(factory, new Profile {
   ID = 1,
   Name = "A",
   Age = 10,
   Address = "T"
  });

  AddToProfile(factory, new Profile {
   ID = 4,
   Name = "A",
   Age = 10,
   Address = "T"
  });

  Console.ReadKey();
 }

 public static void AddToProfile(FlyweightFactory factory, Profile profile)
 {
  Console.WriteLine("\nClient: Adding a profile to database");

  var flyweight = factory.GetFlyweight(new Profile
  {
   ID = profile.ID,
   Name = profile.Name,
   Age = profile.Age,
   Address = profile.Address
  });

  flyweight.Operation(profile);
 }
}

public class Profile
{
 public int ID { get; set; }
 public string Name { get; set; }
 public int Age { get; set; }
 public string Address { get; set; }
}

class FlyweightFactory
{
 private List<Tuple<Flyweight, string>> flyweights = new List<Tuple<Flyweight, string>>();

 public FlyweightFactory(params Profile[] elements)
 {
  foreach (var item in elements)
  {
   flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(item) , this.getKey(item)));
  }
 }

 public string getKey(Profile key)
 {
  List<string> elements = new List<string>();
 
  elements.Add(key.ID.ToString());
  elements.Add(key.Name);
  elements.Add(key.Age.ToString());
  elements.Add(key.Address);
 
  return string.Join("_", elements);
 }
 
 public Flyweight GetFlyweight(Profile SharedState)
 {
  string key = this.getKey(SharedState);
 
  if (flyweights.Where(t => t.Item2 == key).Count() == 0)
  {
   Console.WriteLine("FlyweightFactory: Can't find a flyweight, creating new one.");
   this.flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(SharedState), key));
  }
  else
  {
   Console.WriteLine("FlyweightFactory: Reusing existing flyweight.");
  }
  return this.flyweights.Where(t => t.Item2 == key).FirstOrDefault().Item1;
 }

 public void ListFlyweights()
 {
  var count = flyweights.Count;
  Console.WriteLine($"\nFlyweightFactory: I have {count} flyweights:");
  foreach (var flyweight in flyweights)
  {
   Console.WriteLine(flyweight.Item2);
  }
 }
}

public class Flyweight
{
 private Profile _shareState;

 public Flyweight(Profile profile)
 {
  this._shareState = profile;
 }

 public void Operation(Profile uniqueSate)
 {
  string s = JsonConvert.SerializeObject(this._shareState);
  string u = JsonConvert.SerializeObject(uniqueSate);

  Console.WriteLine($"Flyweight: Displaying shared {s} and unique {u} state.");
 }
}

#2 Web Application Project

Step1 Create the generic type repository mechanism about the flyweight pattern.

Fig 1 Flyweight pattern’s generic type repository – solution explorer

Step 2 Create the Flyweight class file and the FlyweightFactory class file in the Core project.

The Flyweight class file source code shows below:

Fig 2 Flyweight class file source code

The FlyweightFactory class file source code show below:

Fig 3 FlyweightFactory class file source code

Step 3 Create the data transfer object(DTO) of the flyweight pattern in the Core project. This DTO class file name sets “FlyweightDto.”

Fig 4 Flyweight data transfer object(DTO) class file source code

Step 4 Create the services class file of the flyweight pattern in the Core project.

Fig 5 FlyweightServices class file source code

Step 5 Create the Controller file and the index page in the web project.

Step 6 Register a IFlyweight file, a Flyweight class file and a FlyweightServices class file in the web project. Add the register source code in the Startup.cs file of the web project.

services.AddScoped(typeof(IFlyweight<>), typeof(FlyweightRepo<>));
services.AddScoped(typeof(FlyweightServices));
Fig 6 Flyweight pattern result in web project

Reference

davidsky69

Recent Posts

API Gateway in .NET 5 with Ocelot

What is the API gateway? An API gateway is an API management tool that sits…

3 years ago

.NET 5 application with Onion architecture

The .NET 5 SDK is a kind of milestone in the .NET world. The .NET…

4 years ago

SOLID Principles – Dependency inversion principle

In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupling software…

4 years ago

SOLID Principles – Interface segregation principle

In the field of software engineering, the interface segregation principle (ISP) states that no code…

4 years ago

SOLID Principles – Liskov substitution principle

Subtype Requirement: Let  be a property provable about objects  of type T. Then  should be true for objects  of type S where S is…

4 years ago

SOLID Principles – Open-closed principle

In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be…

4 years ago