Якщо ваш бот шпіляє дуже інтенсивно, то аплікація буде просто заганятися кожного разу створювати велику кількість інстансів кожного із Юнітів. Але що цікаво, самі Юніти мають одні і ті ж початкові значення Здоров'я та одне й те саме Зображення. Звичайно із плином гри, Здоров'я зменшується, але картинка, що зображає тварь то одна й та ж сама!
Це може призвести до неефективного використання пам'яті. То як ми можемо зробити загальну інформацію про зображення тваринки (і т.п.) спільною для кожного окремого Юніта одного типу?
1) Перший варіант із створенням об'єктів Зображення для кожного Юніта.
Базовий клас для Юнітів:
public abstract class Unit
{
public string Name { get; protected set; }
public int Health { get; protected set; }
public Image Picture { get; protected set; }
}
І два породжені класи, які зображають Гобліна (Goblin) та Дракона (Dragon) із їхніми початковими значеннями Здоров'я (Health) та Зображення (Picture). Наведемо код Гобліна. Тут слід звернути увагу на те, що зображення Гобліна є дуже велике, тому буде займати багато пам'яті.
public class Goblin : Unit
{
public Goblin()
{
Name = "Goblin";
Health = 8;
Picture = Image.Load("Goblin.jpg");
}
}
Парсер насправді імітує якусь роботу по створенню об'єктів: public class Parser
{
public List<Unit> ParseHTML()
{
var units = new List<Unit>();
for (int i = 0; i < 150; i++)
units.Add(new Dragon());
for (int i = 0; i < 500; i++)
units.Add(new Goblin());
Console.WriteLine("Dragons and Goblins are parsed from HTML page.");
return units;
}
}
То ж ми створили 150 Драконів і 500 Гоблінів, і це забрало нам аж... 439 Mb.
2) То як той Флайвейт працює? (не думаю що когось пів гіга зжертої пам'яті влаштовує)
Просто введемо новий клас, який буде фабрикою Зображень. У нашому випадку Зображення і буде флайвейт об'єктом. Але варто зауважити, що насправді замість Зображення ми б могли шарити більше інформації, скажімо ми б мали базовий клас UnitInitialInfo, який б був полем у класі Unit, а потім фабрика видавали б нам конкретні реалізації цього Info класу. В нашому прикладі ми наводимо тільки створення імейджу для різних тваринок, причому якщо Зображення уже завантажувався для тваринки, то ми його знову не будемо завантажувати.
public class UnitImagesFactory
{
public static Dictionary<Type, Image> Images = new Dictionary<Type, Image>();
public static Image CrateDragonImage()
{
if (!Images.ContainsKey(typeof(Dragon)))
{
Images.Add(typeof(Dragon), Image.Load("Dragon.jpg"));
}
return Images[typeof(Dragon)];
}
public static Image CrateGoblinImage()
{
if (!Images.ContainsKey(typeof(Goblin)))
{
Images.Add(typeof(Goblin), Image.Load("Goblin.jpg"));
}
return Images[typeof(Goblin)];
}
}
І змінимо конструктори Гобліна і Дракона, щоб вони використовували нашу фабрику.
public class Goblin : Unit
{
public Goblin()
{
Name = "Goblin";
Health = 8;
Picture = UnitImagesFactory.CreateGoblinImage();
}
}
Глянемо на UML діаграму цієї чудасії:
Як можна бачити, наша UML діаграма не відповідає класичній діаграмі із GoF книжки, але можна б сказати, що нам слід бути до цього готовими. В реальному світі реалізація патерну часто відрізняється від того, що описано у всіма відомій книзі. Можна дуже дивуватися тому, що люди чітко пробують дотриматися такої ж структури - часто вона буває занадто загальною. Оригінальна стаття автора про Flyweight більш відповідала класичній діаграмі, але там не було добре ясно, що Dog та Dragon є репрезентаціями Info-класів для тваринок.
Тепер в ран-таймі наш чудо-бот зжерає тільки 7 Mb:
Якщо вам сподобалася стаття, то дайте про це знати. Також можна прочитати про інші патерни на блозі автора тут.



Хто добереться до коментарів, я б хотів, щоб дав відповідь на таке питання: Чи є клас UnitImagesFactory якимось із факторі дизайн патернів із книжки GoF? Аргументи в додачу буде дуже добре.
ВідповістиВидалитинажаль цієї книги не читав, як на мене то цей класс схожий на реалізацію звичайного фекторі ) надіюсь на коментарі інших юзерів групи а якщо їх не буде то на відповідь автора.
ВідповістиВидалитипс. таке враження що щастина тексту перекладена гуглом, а то якось читати важко і опечаток трохи є..
ее... я не використовував гугл транслейт. Я перекладав вночі, тому може й багато описок. Знову ж таки питання: чи нормальний стиль у якому той патерн описаний? Я можу попробувати зробити його більш офіційним.
ВідповістиВидалитиНу і крім того в оригінальній статті був дещо інший приклад. Тут я його змінив.
ВідповістиВидалитияк на мене стиль нормальний, так тримати. Більш офіційно можна описати наступний патерн, побачимо що скажуть користувачі.
ВідповістиВидалитиСьогодні говорив з знайомим на рахунок патернів і корисності їх використання, все зводилось до того що патерни вивчити це добре але розумно їх використовувати не завжди получається, тому хотілось би десь почитати про саме проектування, застосування на реальному проекті і тд.
В нас на проекті деякий набір GoF дизайн патернів таки використовується, але дійсно їх багато не запхаєш. А якщо таки запхаєш, то потім із тим кодом дуже фігово розбиратися.
ВідповістиВидалитиМоже порадиш що почитати, думаю такі речі не тільки мене цікавлять... Зараз почав читати "Применение DDD и шаблонов проектирования". Думаю час від часу робити міні звіт в блог по ній, хотя не факт що дочитаю бо я так зрозумів що вони розрахована на трохи вищий рівень ніж зараз у мене.
ВідповістиВидалити"Чи є клас UnitImagesFactory якимось із факторі дизайн патернів із книжки GoF?"
ВідповістиВидалититак, маэмо по суті паттерн Factory Method + кеш
Так це Factory Method. Я хотів бути певним, що ніхто не буде казати що це не той патерн, плутаючи його із параметризованим фекторі методом. Також є така штука як CreateMethod, але вона створює об'єкти зазвичай свого класу і практично завжди є статичними методами.
ВідповістиВидалити