Flyweight Pattern

  • Structural pattern
  • The intent of this pattern is to use sharing to support large number of fine-grained objects efficiently. It does that by sharing parts of the state between these objects instead of keeping all the state in all of the objects.
  • Move the common properties to different class(here Product class). Product class will have Name, Description, Type, Price. Product class is brand new class to achieve the flyweight pattern.
  • Create a new factory – PSFlyWeightFactory. It Caches the Product type.  Brand new class.
  • PSItemFactory – takes the common cached Product + the one varying property serialNumber to create the OrderItem. Existing class, some modification required.
  • Order class – no modification
  • OrderItem – common properties are commented and moved to Product class.
  • Program.cs- few modification required
    • PSFlyWeightFactory pSFlyWeightFactory = new PSFlyWeightFactory();
    • PSItemFactory pSItemFactory = new PSItemFactory(pSFlyWeightFactory);
				
					using FlyweightPattern;

namespace WithoutFlyweightPattern
{
    public class PSItemFactory 
    {
        private readonly PSFlyWeightFactory _pSFlyWeightFactory;
        public PSItemFactory(PSFlyWeightFactory pSFlyWeightFactory)
        {
            _pSFlyWeightFactory = pSFlyWeightFactory;
        }

        public OrderItem Create(PSSeries series, string serialNumber)
        {
            Product product = _pSFlyWeightFactory.Create(series);
            return new OrderItem(product, serialNumber);

            //switch (series)
            //{
            //    case PSSeries.PS5ConsoleEdition:
            //        return new OrderItem("PS5 Console Edition",
            //            "PS5 Console Edition with a Console free", ProductType.GamingConsole, 54990, serialNumber);
            //    case PSSeries.PS5DiscEdition:
            //        return new OrderItem("PS5 Disc Edition",
            //            "PS5 Disc Edition with a webcam", ProductType.GamingConsole, 54990, serialNumber);
            //    case PSSeries.PS4:
            //        return new OrderItem("PS4 Console",
            //            "PS4 Console old but still the best", ProductType.GamingConsole, 25000, serialNumber);
            //    case PSSeries.PS3:
            //        return new OrderItem("PS3 Console Edition",
            //             "PS3 2006 product", ProductType.GamingConsole, 15000, serialNumber);
            //    default:
            //        throw new Exception("Unknown Gaming Console");
            //}
        }
    }

    public enum PSSeries
    {
        PS5DiscEdition,
        PS5ConsoleEdition,
        PS4,
        PS3
    }
}

				
			
				
					using WithoutFlyweightPattern;

namespace FlyweightPattern
{
    public class PSFlyWeightFactory
    {
        private readonly Dictionary<PSSeries, Product> _psSeries;

        public PSFlyWeightFactory()
        {
            _psSeries = new Dictionary<PSSeries, Product>();
        }

        public Product Create(PSSeries series)
        {
            if (!_psSeries.ContainsKey(series))
            {
                switch (series)
                {
                    case PSSeries.PS5ConsoleEdition:
                        _psSeries.Add(series, new Product("PS5 Console Edition",
                        "PS5 Console Edition with a Console free", ProductType.GamingConsole, 54990));
                        break;
                    case PSSeries.PS5DiscEdition:
                        _psSeries.Add(series,new Product("PS5 Disc Edition",
                        "PS5 Disc Edition with a webcam", ProductType.GamingConsole, 54990));
                        break;
                    case PSSeries.PS4:
                        _psSeries.Add(series, new Product("PS4 Console",
                        "PS4 Console old but still the best", ProductType.GamingConsole, 25000));
                        break;
                    case PSSeries.PS3:
                        _psSeries.Add(series, new Product("PS3 Console",
                       "PS3 2006 product", ProductType.GamingConsole, 15000));
                        break;
                    default:
                        break;

                }
            }
            return _psSeries[series];

        }
    }
}

				
			
				
					
using WithoutFlyweightPattern;

namespace FlyweightPattern
{
    public class Product
    {
        public Product(string name, string description, ProductType type, double price)
        {
            Name = name;
            Description = description;
            Type = type;
            Price = price;
        }

        public string Name { get; set; }
        public string Description { get; set; }
        public ProductType Type { get; set; }
        public double Price { get; set; }
    }
}

				
			
				
					using FlyweightPattern;

namespace WithoutFlyweightPattern
{
    public class OrderItem
    {
        //step1: comment 
        //public string Name { get; set; }
        //public string Description { get; set; }
        //public ProductType Type { get; set; }
        //public double Price { get; set; }

        //step2..
        //public Product Product { get; set; }
        //public string SerialNumber { get; set; }

        //step3..no setter
        //make it completely immutable ...

        public Product Product { get;}
        public string SerialNumber { get;}


        public OrderItem(Product product, string serialNumber)
        {
            //Name = name;
            //Description = description;
            //Type = type;
            //Price = price;
            Product = product;
            SerialNumber = serialNumber;
        }
    }

    public enum ProductType
    {
        GamingConsole,
        Desktops,
        Laptop
    }
}

namespace WithoutFlyweightPattern
{
    public class Order
    {
        private readonly List<OrderItem> _items;
        public Order()
        {
            _items = new List<OrderItem>();
        }

        public void Add(OrderItem item)
        {
            _items.Add(item);
        }
    }
}

				
			
				
					using FlyweightPattern;
using System.Text;
using WithoutFlyweightPattern;
class Program
{
    private static int orderCount = 100000;
    static void Main()
    {
         //commen this
        //PSItemFactory pSItemFactory = new PSItemFactory();

        //make this change..
        PSFlyWeightFactory pSFlyWeightFactory = new PSFlyWeightFactory();
        PSItemFactory pSItemFactory = new PSItemFactory(pSFlyWeightFactory);


        List<Order> orders = new List<Order>();
        //from front dropdown you fetch the PS type
        //for example : it is PS5ConsoleEdition
        //1 lakh order count.....
        var orderPsType = PSSeries.PS5ConsoleEdition;
        for (int i = 0; i < orderCount; i++)
        {
            Order order = new Order();
            OrderItem psItem = pSItemFactory.Create(orderPsType, ToBase36((ulong)i));
            order.Add(psItem);
            orders.Add(order);
        }
        Console.ReadKey();
    }

    private static string ToBase36(ulong value)
    {
        const string base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        var sb = new StringBuilder(9);
        do
        {
            sb.Insert(0, base36[(byte)(value % 36)]);
            value /= 36;
        } while (value != 0);

        var paddedString = "ABC" + sb.ToString().PadLeft(6, '0');
        return paddedString;
    }
}
				
			

Leave a Comment