🎉 Ура! Після трьох років роботи, я нарешті випустив англійську версію книжки про патерни! Ось вона »

C#: Легковаговик

Flyweight Легковаговик Flyweight

Легковаговик — це структурний патерн, який економить пам’ять завдяки розподілу спільного стану, винесеного в один об’єкт, між безліччю об’єктів.

Легковаговик дозволяє економити пам’ять, записуючи в кеш однакові дані, що використовуються різними об’єктами.

Детальніше про Легковаговика

Особливості паттерна на C#

Складність:

Популярність:

Застосування: Сенс використання Легковаговика — це економія пам’яті. Тому, якщо в програмі немає такої проблеми, ви навряд чи знайдете там приклади Легковаговика.

Ознаки застосування патерну: Легковаговик можна визначити за створюваними методами класу, які повертають закешовані об’єкти, замість створення нових.

Приклад: Структура патерну

Цей приклад показує структуру патерну Легковаговик, а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.

Program.cs: Приклад структури патерну

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RefactoringGuru.DesignPatterns.Flyweight.Structural
{
    public class Flyweight
    {
        private Car _sharedState;

        public Flyweight(Car car)
        {
            this._sharedState = car;
        }

        public void Operation(Car uniqueState)
        {
            string s = JsonConvert.SerializeObject(this._sharedState);
            string u = JsonConvert.SerializeObject(uniqueState);
            Console.Write($"Flyweight: Displaying shared {s} and unique {u} state.\n");
        }
    }

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

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

        public string getKey(Car key)
        {
            List<string> elements = new List<string>();

            elements.Add(key.Model);
            elements.Add(key.Color);
            elements.Add(key.Company);

            if(key.Owner != null && key.Number != null)
            {
                elements.Add(key.Number);
                elements.Add(key.Owner);
            }

            elements.Sort();

            return string.Join("_", elements);
        }

        public Flyweight GetFlyweight(Car sharedState)
        {
            string key = this.getKey(sharedState);

            if (flyweights.Where(t => t.Item2 == key).Count() == 0)
            {
                Console.Write("FlyweightFactory: Can't find a flyweight, creating new one.\n");
                this.flyweights.Add(new Tuple<Flyweight, string>(new Flyweight(sharedState), key));
            }
            else
            {
                Console.Write("FlyweightFactory: Reusing existing flyweight.\n");
            }
            return this.flyweights.Where(t => t.Item2 == key).FirstOrDefault().Item1;
        }

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

    public class Car
    {
        public string Owner { get; set; }

        public string Number { get; set; }

        public string Company { get; set; }

        public string Model { get; set; }

        public string Color { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();
            client.ClientCode();
        }
    }

    public class Client
    {
        public void addCarToPoliceDatabase(FlyweightFactory factory, Car car)
        {
            Console.Write("\nClient: Adding a car to database.\n");

            var flyweight = factory.GetFlyweight(new Car { Color = car.Color, Model = car.Model, Company = car.Company });
            flyweight.Operation(car);
        }

        public void ClientCode()
        {
            var factory = new FlyweightFactory
                (
                    new Car { Company = "Chevrolet", Model = "Camaro2018", Color = "pink" },
                    new Car { Company = "Mercedes Benz", Model = "C300", Color = "black" },
                    new Car { Company = "Mercedes Benz", Model = "C500", Color = "red" },
                    new Car { Company = "BMW", Model = "M5", Color = "red" },
                    new Car { Company = "BMW", Model = "X6", Color = "white" }
                );
            factory.listFlyweights();

            addCarToPoliceDatabase(factory, 
                new Car { Number = "CL234IR",
                          Owner = "James Doe",
                          Company = "BMW",
                          Model = "M5",
                          Color = "red"
                        });


            addCarToPoliceDatabase(factory,
                new Car
                {
                    Number = "CL234IR",
                    Owner = "James Doe",
                    Company = "BMW",
                    Model = "X1",
                    Color = "red"
                });

            factory.listFlyweights();
        }
    }
}

Output.txt: Результат виконання

FlyweightFactory: I have 5 flyweights:
Camaro2018_Chevrolet_pink
black_C300_Mercedes Benz
C500_Mercedes Benz_red
BMW_M5_red
BMW_white_X6

Client: Adding a car to database.
FlyweightFactory: Reusing existing flyweight.
Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"M5","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"M5","Color":"red"} state.

Client: Adding a car to database.
FlyweightFactory: Can't find a flyweight, creating new one.
Flyweight: Displaying shared {"Owner":null,"Number":null,"Company":"BMW","Model":"X1","Color":"red"} and unique {"Owner":"James Doe","Number":"CL234IR","Company":"BMW","Model":"X1","Color":"red"} state.

FlyweightFactory: I have 6 flyweights:
Camaro2018_Chevrolet_pink
black_C300_Mercedes Benz
C500_Mercedes Benz_red
BMW_M5_red
BMW_white_X6
BMW_red_X1