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

Leave a Reply