Flyweight pattern

De Banane Atomic
Aller à la navigationAller à la recherche

Definition

Use sharing to support large numbers of fine-grained objects efficiently.

  • Split heavy objects into what can be shared (flyweight / template / intrinsic data) and what to be configured (context / extrinsic data)
  • The heavy object can be generated on the fly from the flyweight object and the context
  • Reduce the memory cost of working with large numbers of very small objects

Flyweight vs Singleton

  • flyweight pattern is acting like a common template that can be configured as per the need
  • singleton pattern allows to reuse an existing object

Multithreading

Same problem and remedy as the Singleton pattern.

Exemple

User.cs
public class User
{
    public string Name { get; set; }

    public override string ToString() => $"Simple user: {Name}";
}
Administrator.cs
public class Administrator : User
{
    public override string ToString() => $"Admin user: {Name}";
}
UserFactory.cs
public class UserFactory
{
    IDictionary<UserType, User> userTemplatesByUserType = new Dictionary<UserType, User>();

    public User GetUserFromFactory(UserType userType)
    {
        User userTemplate = null;
        if (userTemplatesByUserType.ContainsKey(userType))
        {
            userTemplate = userTemplatesByUserType[userType];
        }
        else
        {
            switch (userType)
            {
                case UserType.User:
                    userTemplate = new User();
                    userTemplatesByUserType.Add(UserType.User, userTemplate);
                    break;
                case UserType.Administrator:
                    userTemplate = new Administrator();
                    userTemplatesByUserType.Add(UserType.Administrator, userTemplate);
                    break;
                case UserType.Guest:
                    userTemplate = new Guest();
                    userTemplatesByUserType.Add(UserType.Guest, userTemplate);
                    break;
                default:
                    throw new Exception($"Unknown user type {userType}.");
            }
        }

        return userTemplate;
    }
}
Cs.svg
var userFactory = new UserFactory();
var user = userFactory.GetUserFromFactory(UserType.User);
user.Name = "Nicolas";
Console.WriteLine(user);

for (var i = 0; i < 10; i++)
{
    // call only once the Administrator ctor then reuse the instance
    user = userFactory.GetUserFromFactory(UserType.Administrator);
    user.Name = $"Admin{i}";
    Console.WriteLine(user);
}